package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.enums.DefaultTypeEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.EnableEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.field.LinkInfoPojo;
import com.xbongbong.paas.field.LinkedAttrPoJo;
import com.xbongbong.paas.field.MultiUnitItemPoJo;
import com.xbongbong.paas.field.SubFormPoJo;
import com.xbongbong.paas.field.SubRelyFieldPojo;
import com.xbongbong.paas.field.UnitItemPoJo;
import com.xbongbong.paas.help.FormDataValidateProductHelp;
import com.xbongbong.paas.help.PaasFormHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.help.ProGetHelp;
import com.xbongbong.paas.help.UserHelp;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.pojo.MultiUnitPricePoJo;
import com.xbongbong.paas.pojo.dto.ParseSingleRowDataDTO;
import com.xbongbong.paas.pojo.dto.UserAndDepartmentGetDTO;
import com.xbongbong.paas.pojo.vo.LinkResultDataDTO;
import com.xbongbong.paas.pojo.vo.LinkResultDataVO;
import com.xbongbong.paas.pojo.vo.ParseSingleRowDataVO;
import com.xbongbong.paas.pojo.vo.UserAndDepartmentGetVO;
import com.xbongbong.paas.service.PaasAppService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CloneUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.parent.parse.data.FormDataLinkDataLinkProductServiceImpl;
import com.xbongbong.parent.parse.data.FormDataUpdateGetAnalysisDataHelp;
import com.xbongbong.parent.parse.data.LinkProductUpdateGetServiceImpl;
import com.xbongbong.pro.businessproduct.pojo.dto.BusinessProductBatchListDTO;
import com.xbongbong.pro.businessproduct.pojo.dto.BusinessProductListDTO;
import com.xbongbong.pro.businessproduct.pojo.dto.BusinessProductListRelyDTO;
import com.xbongbong.pro.businessproduct.pojo.dto.BussinessProductBatchAutoMatchDTO;
import com.xbongbong.pro.businessproduct.pojo.vo.BusinessProductBatchListVO;
import com.xbongbong.pro.businessproduct.pojo.vo.BusinessProductListRelyVO;
import com.xbongbong.pro.businessproduct.pojo.vo.BusinessProductListVO;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.detailtab.dto.DetailTabDataGetDTO;
import com.xbongbong.pro.detailtab.vo.ProductSummaryVO;
import com.xbongbong.pro.domain.entity.LinkProductRelyEntity;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.TemplateErrorCodeEnum;
import com.xbongbong.pro.product.pojo.dto.PagingProductDTO;
import com.xbongbong.pro.product.pojo.vo.PagingProductVO;
import com.xbongbong.pro.product.pojo.vo.RelationProductListVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.MultiUnitConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.ProductConstant;
import com.xbongbong.saas.constant.StockConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.BomProductEntity;
import com.xbongbong.saas.domain.entity.BusinessProductEntity;
import com.xbongbong.saas.domain.entity.ContractProductEntity;
import com.xbongbong.saas.domain.entity.OpportunityProductEntity;
import com.xbongbong.saas.domain.entity.OutstockProductEntity;
import com.xbongbong.saas.domain.entity.QuotationProductEntity;
import com.xbongbong.saas.domain.entity.UserTeamEntity;
import com.xbongbong.saas.domain.entity.WorkOrderExplainEntity;
import com.xbongbong.saas.domain.entity.ext.BomBillEntityExt;
import com.xbongbong.saas.domain.entity.ext.ContractEntityExt;
import com.xbongbong.saas.domain.entity.ext.QuotationEntityExt;
import com.xbongbong.saas.enums.InstockTypeEnum;
import com.xbongbong.saas.enums.ListOptionEnum;
import com.xbongbong.saas.enums.OutstockTypeEnum;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.UpdateDataTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.BomBillEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.ContractOutstockEnum;
import com.xbongbong.saas.enums.business.InstockEnum;
import com.xbongbong.saas.enums.business.OutstockEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.ProductionOrderEnum;
import com.xbongbong.saas.enums.business.QuotationEnum;
import com.xbongbong.saas.enums.business.RefundEnum;
import com.xbongbong.saas.enums.product.ContractOutstockProductEnum;
import com.xbongbong.saas.enums.product.ContractProductEnum;
import com.xbongbong.saas.enums.product.InstockProductEnum;
import com.xbongbong.saas.enums.product.OutstockProductEnum;
import com.xbongbong.saas.enums.product.ProductionOrderFinishProductEnum;
import com.xbongbong.saas.enums.product.ProductionOrderMaterielProductEnum;
import com.xbongbong.saas.enums.product.PurchaseProductEnum;
import com.xbongbong.saas.enums.product.QuotationProductEnum;
import com.xbongbong.saas.enums.product.RefundInstockProductEnum;
import com.xbongbong.saas.enums.product.RefundProductEnum;
import com.xbongbong.saas.help.FormDataAnalysisHelp;
import com.xbongbong.saas.help.RelativeProductHelp;
import com.xbongbong.saas.model.BomBillModel;
import com.xbongbong.saas.model.BomProductModel;
import com.xbongbong.saas.model.ContractModel;
import com.xbongbong.saas.model.ContractProductModel;
import com.xbongbong.saas.model.LinkProductRelyModel;
import com.xbongbong.saas.model.OpportunityProductModel;
import com.xbongbong.saas.model.OutstockProductModel;
import com.xbongbong.saas.model.ProductUnitPriceModel;
import com.xbongbong.saas.model.QuotationModel;
import com.xbongbong.saas.model.QuotationProductModel;
import com.xbongbong.saas.model.WarehouseModel;
import com.xbongbong.saas.model.WorkOrderExplainModel;
import com.xbongbong.saas.service.AssembleService;
import com.xbongbong.saas.service.BomBillService;
import com.xbongbong.saas.service.BusinessProductService;
import com.xbongbong.saas.service.ContractService;
import com.xbongbong.saas.service.CostAdjustService;
import com.xbongbong.saas.service.InstockService;
import com.xbongbong.saas.service.InventoryService;
import com.xbongbong.saas.service.OpportunityService;
import com.xbongbong.saas.service.OrderService;
import com.xbongbong.saas.service.OutstockService;
import com.xbongbong.saas.service.ProductService;
import com.xbongbong.saas.service.ProductStockInfoService;
import com.xbongbong.saas.service.ProductionOrderService;
import com.xbongbong.saas.service.PurchaseService;
import com.xbongbong.saas.service.QuotationService;
import com.xbongbong.saas.service.RefundService;
import com.xbongbong.saas.service.ReturnService;
import com.xbongbong.saas.service.ReturnedPurchaseService;
import com.xbongbong.saas.service.SupplierService;
import com.xbongbong.saas.service.TransferService;
import com.xbongbong.saas.service.UserTeamService;
import com.xbongbong.saas.service.WorkOrderService;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getDoubleOrDefaultFromFormData;
import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getIntegerOrDefaultFromFormData;

/**
 * 业务产品service层接口实现类
 *
 * @author chaoxiong.lei
 * @date 2019/3/7 16:01
 */
@Service("BusinessProductService")
public class BusinessProductServiceImpl implements BusinessProductService {

    private static final Logger LOG = LoggerFactory.getLogger(BusinessProductServiceImpl.class);

    @Resource
    private TransferService transferService;
    @Resource
    private InventoryService inventoryService;
    @Resource
    private ProductStockInfoService productStockInfoService;
    @Resource
    private BomBillService bomBillService;
    @Resource
    private ProductionOrderService productionOrderService;
    @Resource
    private OutstockService outstockService;
    @Resource
    private InstockService instockService;
    @Resource
    private PurchaseService purchaseService;
    @Resource
    private ReturnedPurchaseService returnedPurchaseService;
    @Resource
    private SupplierService supplierService;
    @Resource
    private AssembleService assembleService;
    @Resource
    private ContractService contractService;
    @Resource
    private OpportunityService opportunityService;
    @Resource
    private RefundService refundService;
    @Resource
    private WorkOrderService workOrderService;
    @Resource
    private QuotationService quotationService;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private ProductService productService;
    @Resource
    private UserHelp userHelp;
    @Resource
    private ProGetHelp proGetHelp;
    @Resource
    private UserTeamService userTeamService;
    @Resource
    private FormDataLinkDataLinkProductServiceImpl formDataLinkDataLinkProductService;
    @Resource
    private FormDataValidateProductHelp formDataValidateProductHelp;
    @Resource
    private WorkOrderExplainModel workOrderExplainModel;
    @Resource
    private BomProductModel bomProductModel;
    @Resource
    private OpportunityProductModel opportunityProductModel;
    @Resource
    private BomBillModel bomBillModel;
    @Resource
    private QuotationProductModel quotationProductModel;
    @Resource
    private QuotationModel quotationModel;
    @Resource
    private ContractProductModel contractProductModel;
    @Resource
    private PaasFormHelp paasFormHelp;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private FormDataUpdateGetAnalysisDataHelp formDataUpdateGetAnalysisDataHelp;
    @Resource
    private LinkProductUpdateGetServiceImpl linkProductUpdateGetService;
    @Resource
    private OutstockProductModel outstockProductModel;
    @Resource
    private PaasAppService paasAppService;
    @Resource
    private LinkProductRelyModel linkProductRelyModel;
    @Resource
    private WarehouseModel warehouseModel;
    @Resource
    private ProductUnitPriceModel productUnitPriceModel;
    @Resource
    private RelativeProductHelp relativeProductHelp;
    @Resource
    private OrderService orderService;
    @Resource
    private ReturnService returnService;
    @Resource
    private FormDataAnalysisHelp formDataAnalysisHelp;
    @Resource
    private ContractModel contractModel;
    @Resource
    private CostAdjustService costAdjustService;
    @Override
    public BusinessProductListVO getBusinessProductList(BusinessProductListDTO businessProductListDTO) throws XbbException{
        Integer businessType = businessProductListDTO.getBusinessType();
        // 前端传退货退款ID，查询退货退款ES
        boolean refund = true;
        if(Objects.equals(businessProductListDTO.getSourceBusinessType(), XbbRefTypeEnum.REFUND.getCode())){
            businessType = XbbRefTypeEnum.REFUND.getCode();
            // 前端传合同ID
            refund = false;
            businessProductListDTO.setBusinessType(businessType);
        }
        RedundantTemplateTypeEnum templateTypeEnum = RedundantTemplateTypeEnum.getByCode(businessType);
        BusinessProductListVO businessProductListVO = new BusinessProductListVO();
        switch (templateTypeEnum) {
            case TRANSFER:
//                businessProductListVO = transferService.getTransferProductList(businessProductListDTO, null);
                break;
            case INVENTORY:
//                businessProductListVO = inventoryService.getInventoryProductList(businessProductListDTO, null);
                break;
            case BOMBILL:
                businessProductListVO = bomBillService.getBomProductList(businessProductListDTO, null);
                break;
            case PRODUCTIONORDER:
//                businessProductListVO = productionOrderService.getProductionOrderProductList(businessProductListDTO, null);
                break;
            case INSTOCK:
            case PURCHASE_INSTOCK:
            case REFUND_INSTOCK:
            case OTHER_INSTOCK:
            case PRODUCTION_INSTOCK:
            case RETURNED_MATERIEL_INSTOCK:
//                businessProductListVO = instockService.getInstockProductList(businessProductListDTO, null);
                break;
            case OUTSTOCK:
            case CONTRACT_OUTSTOCK:
            case RETURNED_PURCHASE_OUTSTOCK:
            case OTHER_OUTSTOCK:
            case PRODUCTION_MATERIEL_OUTSTOCK:
            case WORK_ORDER_OUTSTOCK:
//                businessProductListVO = outstockService.getOutstockProductList(businessProductListDTO, null);
                break;
            case PURCHASE:
//                businessProductListVO = purchaseService.getPurchaseProductList(businessProductListDTO, null);
                break;
            case RETURNED_PURCHASE:
//                businessProductListVO = returnedPurchaseService.getReturnedPurchaseProductList(businessProductListDTO, null);
                break;
            case SUPPLIER:
//                businessProductListVO = supplierService.getSupplierProductList(businessProductListDTO, null);
                break;
            case ASSEMBLE:
//                businessProductListVO = assembleService.getAssembleProductList(businessProductListDTO, null);
                break;
            case CONTRACT:
//                businessProductListVO = contractService.getContractProductList(businessProductListDTO, null);
                break;
            case SALES_OPPORTUNITY:
//                businessProductListVO = opportunityService.getOpportunityProductList(businessProductListDTO, null);
                break;
            case REFUND:
//                businessProductListVO = refundService.getRefundProductList(businessProductListDTO, null, refund);
                break;
            case WORKORDER:
                businessProductListVO = workOrderService.getWorkOrderProductList(businessProductListDTO,null);
                break;
            case QUOTATION:
//                businessProductListVO = quotationService.getQuotationProductList(businessProductListDTO);
                break;
            default:
                break;
        }
        return businessProductListVO;
    }

    @Override
    public BusinessProductListVO getBusinessProductList(DetailTabDataGetDTO detailTabDataGetDTO) throws XbbException {
        BusinessProductListDTO businessProductListDTO = new BusinessProductListDTO();
        BeanUtil.copyProperties(detailTabDataGetDTO, businessProductListDTO);
        // 详情页获取产品
        businessProductListDTO.setDetailGet(true);
        return getBusinessProductList(businessProductListDTO);
    }

    @Override
    public ProductSummaryVO summaryProductList(DetailTabDataGetDTO detailTabDataGetDTO) throws XbbException {
        BusinessProductListDTO businessProductListDTO = new BusinessProductListDTO();
        BeanUtil.copyProperties(detailTabDataGetDTO, businessProductListDTO);
        // 详情页获取产品
        businessProductListDTO.setDetailGet(true);
        Integer businessType4Distributor = XbbRefTypeEnum.transferBusinessType4Distributor(businessProductListDTO.getBusinessType(), businessProductListDTO.getDistributorMark());
        RedundantTemplateTypeEnum templateTypeEnum = RedundantTemplateTypeEnum.getByCode(businessType4Distributor);
        ProductSummaryVO productSummaryVO = new ProductSummaryVO();
        switch (templateTypeEnum) {
            case TRANSFER:
                productSummaryVO = transferService.summaryProductList(businessProductListDTO);
                break;
            case INVENTORY:
                productSummaryVO = inventoryService.summaryProductList(businessProductListDTO);
                break;
            case BOMBILL:
                productSummaryVO = bomBillService.summaryProductList(businessProductListDTO);
                break;
            case PRODUCTIONORDER:
                productSummaryVO = productionOrderService.summaryProductList(businessProductListDTO);
                break;
            case INSTOCK:
                productSummaryVO = instockService.summaryProductList(businessProductListDTO);
                break;
            case OUTSTOCK:
            case CONTRACT_OUTSTOCK:
            case WORK_ORDER_OUTSTOCK:
            case RETURNED_PURCHASE_OUTSTOCK:
            case PRODUCTION_MATERIEL_OUTSTOCK:
            case OTHER_OUTSTOCK:
            case ORDER_OUTSTOCK:
                productSummaryVO = outstockService.summaryProductList(businessProductListDTO);
                break;
            case PURCHASE:
                productSummaryVO = purchaseService.summaryProductList(businessProductListDTO);
                break;
            case RETURNED_PURCHASE:
                productSummaryVO = returnedPurchaseService.summaryProductList(businessProductListDTO);
                break;
            case SUPPLIER:
                productSummaryVO = supplierService.summaryProductList(businessProductListDTO);
                break;
            case CONTRACT:
                productSummaryVO = contractService.summaryProductList(businessProductListDTO);
                break;
            case SALES_OPPORTUNITY:
                productSummaryVO = opportunityService.summaryProductList(businessProductListDTO);
                break;
            case REFUND:
                productSummaryVO = refundService.summaryProductList(businessProductListDTO);
                break;
            case WORKORDER:
                productSummaryVO = workOrderService.summaryProductList(businessProductListDTO);
                break;
            case QUOTATION:
                productSummaryVO = quotationService.summaryProductList(businessProductListDTO);
                break;
            case ORDER:
                productSummaryVO = orderService.summaryProductList(businessProductListDTO);
                break;
            case RETURN:
                productSummaryVO = returnService.summaryProductList(businessProductListDTO);
                break;
            default:
                break;
        }
        return productSummaryVO;
    }

    @Override
    public RelationProductListVO getRelationProductList(DetailTabDataGetDTO detailTabDataGetDTO) throws XbbException {
        Long dataId = detailTabDataGetDTO.getDataId();
        String corpid = detailTabDataGetDTO.getCorpid();
        Integer businessType = detailTabDataGetDTO.getBusinessType();
        PaasFormDataEntityExt formDataEntityExt = proGetHelp.getByKey(dataId, businessType, detailTabDataGetDTO.getSaasMark(), corpid);
        if (Objects.isNull(formDataEntityExt)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }
        String explains;
        if (Objects.equals(detailTabDataGetDTO.getBusinessType(), RedundantTemplateTypeEnum.WORKORDER.getCode())) {
            WorkOrderExplainEntity workOrderExplainEntity = workOrderExplainModel.getByFormId(formDataEntityExt.getFormId(), corpid);
            if (Objects.isNull(workOrderExplainEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            explains = workOrderExplainEntity.getExplains();
        } else {
            PaasFormExplainEntity formExplainEntity = paasFormExplainModel.getByFormId(formDataEntityExt.getFormId(), corpid);
            if (Objects.isNull(formExplainEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            explains = formExplainEntity.getExplains();
        }
        RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(businessType);
        JSONObject data = new JSONObject();
        RelationProductListVO relationProductListVO = new RelationProductListVO();
        PagingProductDTO pagingProductDTO = new PagingProductDTO();
        BeanUtil.copyProperties(detailTabDataGetDTO, pagingProductDTO);
        pagingProductDTO.setData(data);
        pagingProductDTO.setUpdateDataTypeEnum(UpdateDataTypeEnum.DETAIL);
        PagingProductVO pagingProductVO = new PagingProductVO();
        String productAttr = detailTabDataGetDTO.getAttr() == null ? ContractEnum.PRODUCT.getAttr() : detailTabDataGetDTO.getAttr();
        switch (redundantTemplateTypeEnum) {
            case CONTRACT:
                pagingProductVO  = contractService.getPagingProduct(pagingProductDTO);
                break;
            case REFUND:
                Long redContractId = formDataEntityExt.getData().getLong(RefundEnum.RED_CONTRACT_ID.getAttr());
                pagingProductDTO.setDataId(redContractId);
                if (Objects.isNull(redContractId) || Objects.equals(redContractId, 0L)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }
                pagingProductVO  = refundService.getPagingProduct(pagingProductDTO);
                break;
            case SALES_OPPORTUNITY:
                pagingProductVO  = opportunityService.getPagingProduct(pagingProductDTO);
                break;
            case INSTOCK:
            case PURCHASE_INSTOCK:
            case REFUND_INSTOCK:
            case OTHER_INSTOCK:
            case PRODUCTION_INSTOCK:
            case RETURNED_MATERIEL_INSTOCK:
                pagingProductVO  = instockService.getPagingProduct(pagingProductDTO);
                break;
            case OUTSTOCK:
            case RETURNED_PURCHASE_OUTSTOCK:
            case WORK_ORDER_OUTSTOCK:
            case OTHER_OUTSTOCK:
                pagingProductVO  = outstockService.getPagingProduct(pagingProductDTO);
                break;
            case PRODUCTION_MATERIEL_OUTSTOCK:
                pagingProductVO = outstockService.getPagingProductionMaterielOutstockProduct(pagingProductDTO);
                break;
            case CONTRACT_OUTSTOCK:
                pagingProductVO  = outstockService.getPagingContractOutstockProduct(pagingProductDTO);
                break;
            case SUPPLIER:
                pagingProductVO  = supplierService.getPagingProduct(pagingProductDTO);
                break;
            case PURCHASE:
                pagingProductVO  = purchaseService.getPagingProduct(pagingProductDTO);
                break;
            case RETURNED_PURCHASE:
                pagingProductVO  = returnedPurchaseService.getPagingProduct(pagingProductDTO);
                break;
            case TRANSFER:
                pagingProductVO  = transferService.getPagingProduct(pagingProductDTO);
                break;
            case INVENTORY:
                pagingProductVO  = inventoryService.getPagingProduct(pagingProductDTO);
                break;
            case WORKORDER:
                pagingProductVO  = workOrderService.getPagingProduct(pagingProductDTO);
                break;
            case BOMBILL:
                pagingProductVO  = bomBillService.getPagingProduct(pagingProductDTO);
                break;
            case PRODUCTIONORDER:
                pagingProductVO  = productionOrderService.getPagingProduct(pagingProductDTO);
                break;
            case ASSEMBLE:
                pagingProductVO  = assembleService.getPagingProduct(pagingProductDTO);
                break;
            case QUOTATION:
                pagingProductVO = quotationService.getPagingProduct(pagingProductDTO);
                break;
            case COST_ADJUST:
                pagingProductVO = costAdjustService.getPagingProduct(pagingProductDTO);
                break;
            default:
               throw new XbbException(TemplateErrorCodeEnum.API_ERROR_350006);
        }
        PageHelper pageHelper = pagingProductVO.getPageHelper();
        JSONArray productDataArr = pagingProductVO.getProductDataArr();
        List<PaasFormDataEntityExt> formDataList = new ArrayList<>();
        for (int i = 0; i < productDataArr.size(); i ++) {
            JSONObject jsonData = productDataArr.getJSONObject(i);
            PaasFormDataEntityExt paasFormDataEntityExt = new PaasFormDataEntityExt();
            paasFormDataEntityExt.setData(jsonData);
            formDataList.add(paasFormDataEntityExt);
        }
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explains, productAttr);
        FieldAttrEntity fieldAttrEntity = explainMap.get(productAttr);
        proFormHelp.setProductAccuracy(fieldAttrEntity,corpid,detailTabDataGetDTO.getUserId());
        SubFormPoJo subForm = fieldAttrEntity.getSubForm();
        List<FieldAttrEntity> fieldAttrEntityList = (List<FieldAttrEntity>) subForm.getItems();
        Map<Long, PaasFormExplainEntity> formExplainMap = paasFormHelp.getLinkFormExplain(fieldAttrEntityList, corpid);
        Map<Long, WorkOrderExplainEntity> workOrderExplainMap = paasFormHelp.getWorkOrderLinkFormExplain(fieldAttrEntityList, corpid);

        Set<Object> linkDataSet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, FieldAttrEntity> subExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (int i = 0; i < fieldAttrEntityList.size(); i ++) {
            FieldAttrEntity entity = fieldAttrEntityList.get(i);
            if (Objects.equals(entity.getFieldType(), FieldTypeEnum.LINK_DATA.getType()) || Objects.equals(entity.getFieldType(), FieldTypeEnum.LINK_DATA_MULTI.getType())) {
                LinkInfoPojo linkInfo = entity.getLinkInfo();
                List<LinkedAttrPoJo> linkedShowAttr = linkInfo.getLinkedShowAttr();
                Map<String, FieldAttrEntity> linkExplain;
                if (!Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), linkInfo.getLinkBusinessType())) {
                    PaasFormExplainEntity paasFormExplainEntity = formExplainMap.get(linkInfo.getLinkFormId());
                    if (Objects.isNull(paasFormExplainEntity)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
                    }
                    linkExplain = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
                } else {
                    WorkOrderExplainEntity paasFormExplainEntity = workOrderExplainMap.get(linkInfo.getLinkFormId());
                    if (Objects.isNull(paasFormExplainEntity)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
                    }
                    linkExplain = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
                }
                if (CollectionUtils.isNotEmpty(linkedShowAttr)) {
                    for (int j = 0; j < linkedShowAttr.size(); j ++) {
                        LinkedAttrPoJo linkedAttrPoJo = linkedShowAttr.get(j);
                        FieldAttrEntity linkedAttr = linkExplain.get(linkedAttrPoJo.getAttr());
                        if (Objects.nonNull(linkedAttr.getLinkDetail())) {
                            linkedAttr.setLinkDetail(null);
                        }
                        linkedAttr.setAttr(linkInfo.getLinkBusinessType() + StringConstant.COMMA + linkedAttrPoJo.getAttr());
                        linkedAttr.setAttrName(linkedAttrPoJo.getAttrName());
                        linkedAttr.setTheWidth(linkedAttrPoJo.getTheWidth());
                        linkedAttr.setWidthAttr(linkedAttrPoJo.getWidthAttr());
                        linkedAttr.setFixed(linkedAttrPoJo.getFixed());
                        linkedAttr.setFreezeCount(linkedAttrPoJo.getFreezeCount());
                        // 关联数据字段本身的linkShowAttrList的更新
                        BeanUtil.copyProperties(linkedAttr, linkedAttrPoJo);
                        linkedAttr.setAttrNameEn(linkedAttr.getAttrNameEn());
                        fieldAttrEntityList.add(i + 1 + j, linkedAttr);
                    }
                }
            }
        }
        fieldAttrEntityList.removeIf(field -> !UpdateDataTypeEnum.DETAIL.formatShow(field.getShowType()));
        fieldAttrEntityList.removeIf(field -> Objects.equals(field.getVisible(), 0) || Objects.equals(field.getIsOpen(), 2));
        if (Objects.equals(businessType,XbbRefTypeEnum.REFUND.getCode())){
            Boolean isJxcUse = paasAppService.validateAppEnable(null, XbbRefTypeEnum.JXC.getAlias(), SaasMarkEnum.SAAS.getCode(), corpid);
            if (!isJxcUse) {
                fieldAttrEntityList.removeIf(field -> (Objects.equals(field.getAttr(), SelectProductEnum.SOURCE_DOC.getAttr())
                        || Objects.equals(field.getAttr(), RefundProductEnum.INSTOCK_NUM.getAttr())
                        || Objects.equals(field.getAttr(), RefundProductEnum.WAIT_INSTOCK_NUM.getAttr())
                        || Objects.equals(field.getAttr(), RefundProductEnum.BATCH.getAttr())
                        || Objects.equals(field.getAttr(), RefundProductEnum.GUARANTEE_PERIOD.getAttr())
                        || Objects.equals(field.getAttr(), RefundProductEnum.PRODUCE_DATE.getAttr())
                        || Objects.equals(field.getAttr(), RefundProductEnum.EXPIRE_DATE.getAttr()))
                        || Objects.equals(field.getAttr(), RefundProductEnum.REFUND_STATUS.getAttr()));
            }
        } else if (Objects.equals(businessType,XbbRefTypeEnum.CONTRACT.getCode())){
            Boolean isJxcUse = paasAppService.validateAppEnable(null, XbbRefTypeEnum.JXC.getAlias(), SaasMarkEnum.SAAS.getCode(), corpid);
            if (!isJxcUse) {
                fieldAttrEntityList.removeIf(field -> (Objects.equals(field.getAttr(), SelectProductEnum.OUT_OF_STOCK.getAttr())
                        || Objects.equals(field.getAttr(),SelectProductEnum.CONTRACT_STATUS.getAttr())
                        || Objects.equals(field.getAttr(),SelectProductEnum.OUTSTOCK_NUM.getAttr())
                        || Objects.equals(field.getAttr(),SelectProductEnum.WAIT_OUTSTOCK_NUM.getAttr())
                        || Objects.equals(field.getAttr(),SelectProductEnum.RETURN_NUM.getAttr())));
            }
        }else if (Objects.equals(businessType,XbbRefTypeEnum.WORK_ORDER.getCode())){
            Boolean isJxcUse = paasAppService.validateAppEnable(null, XbbRefTypeEnum.JXC.getAlias(), SaasMarkEnum.SAAS.getCode(), corpid);
            if (!isJxcUse) {
                fieldAttrEntityList.removeIf(field -> (Objects.equals(field.getAttr(), SelectProductEnum.OUTSTOCK_NUM.getAttr())
                        || Objects.equals(field.getAttr(),SelectProductEnum.WAIT_OUTSTOCK_NUM.getAttr())));
            }
        } else if (Objects.equals(businessType, XbbRefTypeEnum.SUPPLIER.getCode())) {
            Boolean permissions = supplierService.verifyEditPermissions(detailTabDataGetDTO);
            if (permissions) {
                FieldAttrEntity linkProductField = new FieldAttrEntity();
                linkProductField.setAttr(ListOptionEnum.OPTION.getAttr());
                linkProductField.setAttrName(ListOptionEnum.OPTION.getAttrName());
                linkProductField.setFieldType(FieldTypeEnum.OPTION.getType());
                linkProductField.setDisableListSort(1);
                linkProductField.setAttrNameEn(linkProductField.getAttrNameEn());
                fieldAttrEntityList.add(0, linkProductField);
            }
        }

        // 移动端暂不支持子表单 附件 星级 生日
        List<Integer> mobileNotSupportFieldType = new ArrayList<>();
        mobileNotSupportFieldType.add(FieldTypeEnum.SUB_FORM.getType());
        mobileNotSupportFieldType.add(FieldTypeEnum.UPLOAD.getType());
        mobileNotSupportFieldType.add(FieldTypeEnum.STAR.getType());
        mobileNotSupportFieldType.add(FieldTypeEnum.BIRTHDAY.getType());
        fieldAttrEntityList.removeIf(field -> Objects.equals(detailTabDataGetDTO.getPlatform(), PlatFormEnum.DINGTALK.getValue()) && mobileNotSupportFieldType.contains(field.getFieldType()));
        Map<String,Object> thousandExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (FieldAttrEntity entity : fieldAttrEntityList) {
            subExplainMap.put(entity.getAttr(), entity);
            if (SelectProductEnum.ThousandBitsAttr(entity.getAttr())){
                thousandExplainMap.put(entity.getAttr(),entity);
            }
        }
        UserAndDepartmentGetDTO userAndDepartmentGetDTO = new UserAndDepartmentGetDTO();
        BeanUtil.copyProperties(detailTabDataGetDTO, userAndDepartmentGetDTO);
        UserAndDepartmentGetVO userAndDepartmentGetVO = userHelp.getUserDepartmentMap(userAndDepartmentGetDTO);
        Map<String, UserEntity> userMap = userAndDepartmentGetVO.getUserMap();
        Map<String, DepartmentEntity> departmentMap = userAndDepartmentGetVO.getDepartmentMap();
        List<Long> dataIdList = new ArrayList<>();
        //协同团队
        Map<Integer, List<UserTeamEntity>> userTeamMap = userTeamService.getUserTeam(dataId, corpid, businessType);
        List<String> ownerIds = new ArrayList<>();
        List<String> coUserIds = new ArrayList<>();
        for (Map.Entry<Integer, List<UserTeamEntity>> entry : userTeamMap.entrySet()) {
            if (Objects.equals(entry.getKey(), BasicConstant.MAIN_USER)) {
                entry.getValue().forEach(team -> ownerIds.add(team.getUserId()));
            } else if (Objects.equals(entry.getKey(), BasicConstant.COOP_USER)) {
                entry.getValue().forEach(team -> coUserIds.add(team.getUserId()));
            }
        }
        List<PaasFormDataEntityExt> linkDataList = new ArrayList<>();
        for (PaasFormDataEntityExt paasFormDataEntity : formDataList) {
            JSONObject linkProductData = paasFormDataEntity.getData();
            ParseSingleRowDataDTO parseSingleRowDataDTO = new ParseSingleRowDataDTO();
            BeanUtil.copyProperties(detailTabDataGetDTO, parseSingleRowDataDTO);
            parseSingleRowDataDTO.setDataJsonObject(linkProductData);
            parseSingleRowDataDTO.setUserMap(userMap);
            parseSingleRowDataDTO.setDepartmentMap(departmentMap);
            parseSingleRowDataDTO.setExplainMap(subExplainMap);
            parseSingleRowDataDTO.setCreatorId(formDataEntityExt.getCreatorId());
            // 像出入库单没有负责人团队，直接取单据的负责人
            if (CollectionsUtil.isEmpty(ownerIds)){
                ownerIds.add(formDataEntityExt.getOwnerId());
            }
            parseSingleRowDataDTO.setOwnerId(ownerIds);
            parseSingleRowDataDTO.setCoUserId(coUserIds);
            parseSingleRowDataDTO.setDetailFlag(1);
            ParseSingleRowDataVO parseSingleRowDataVO = linkProductUpdateGetService.parseSingleRowData(parseSingleRowDataDTO);
            if(Objects.isNull(parseSingleRowDataVO)){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PARSE_SINGLE_ROW_DATA_FAILED);
            }
            LinkResultDataVO linkResultDataVO = parseSingleRowDataVO.getLinkResultDataVO();
            JSONObject resultObject = parseSingleRowDataVO.getResult();
            if (!linkResultDataVO.getLinkDataSet().isEmpty()) {
                linkDataSet.addAll(linkResultDataVO.getLinkDataSet());
            }

            //千分位解析
            for (String attr : resultObject.keySet()) {
                // 详情tab是否启用金额
                if (SelectProductEnum.ThousandBitsAttr(attr) && Objects.nonNull(thousandExplainMap.get(attr))){
                    if (Objects.equals(((FieldAttrEntity)thousandExplainMap.get(attr)).getAmountFlag(),1)){
                        formDataAnalysisHelp.analysisAmountOfThousandBitsNomal(resultObject, attr, thousandExplainMap, false);
                    }
                }
            }

            paasFormDataEntity.setData(resultObject);
            linkDataList.add(paasFormDataEntity);
        }
        // 获取数据
        LinkResultDataVO linkResultDataVO = new LinkResultDataVO();
        linkResultDataVO.setExplainMap(subExplainMap);
        linkResultDataVO.setUserMap(userMap);
        linkResultDataVO.setDepartmentMap(departmentMap);
        linkResultDataVO.setLinkDataSet(linkDataSet);
        linkResultDataVO.setFormDataList(linkDataList);
        linkResultDataVO.setExplainList(fieldAttrEntityList);
        if(!linkDataSet.isEmpty()){
            LinkResultDataDTO linkResultDataDTO = new LinkResultDataDTO();
            BeanUtil.copyProperties(detailTabDataGetDTO, linkResultDataDTO);
            formDataLinkDataLinkProductService.formDataLinkDataShowGet(linkResultDataDTO, linkResultDataVO);
        }
        List<PaasFormDataEntityExt> resultList = linkResultDataVO.getFormDataList();

        for (PaasFormDataEntityExt paasFormDataEntityExt : resultList) {
            JSONObject extData = paasFormDataEntityExt.getData();
            if (!extData.containsKey(SelectProductEnum.NUM.getAttr()) || Objects.isNull(extData.get(SelectProductEnum.NUM.getAttr()))) {
                extData.put(ProductEnum.ENABLE_SERIAL_NUMBER.getSaasAttr(), BasicConstant.ZERO);
            }
        }
        fieldAttrEntityList.forEach(item->{
            if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), item.getFieldType())) {
                item.setFieldType(FieldTypeEnum.TEXT.getType());
            }
        });
        relationProductListVO.setHeadList(fieldAttrEntityList);
        relationProductListVO.setFormDataList(resultList);
        relationProductListVO.setPageHelper(pageHelper);
        return relationProductListVO;
    }

    @Override
    public BusinessProductBatchListVO getBusinessProductBathList(BusinessProductBatchListDTO businessProductBatchListDTO) throws XbbException {
        return productStockInfoService.getNewProductBatchList(businessProductBatchListDTO);
    }

    @Override
    public BusinessProductListRelyVO businessProductListGetRely(BusinessProductListRelyDTO businessProductListRelyDTO) throws XbbException {
        String corpid = businessProductListRelyDTO.getCorpid();
        if (Objects.equals(corpid, "ding8e6733b0f55f17a435c2f4657eb6378f")) {
            LOG.info("corpid="+ corpid + "》dto=" + JSON.toJSONString(businessProductListRelyDTO));
        }
        Long refId = businessProductListRelyDTO.getDataId();
        Integer type = businessProductListRelyDTO.getType();
        Integer businessType = businessProductListRelyDTO.getBusinessType();
        List<Integer> sourceTypeList = Arrays.asList(XbbRefTypeEnum.REFUND.getCode(), XbbRefTypeEnum.RETURNED_PURCHASE.getCode(), XbbRefTypeEnum.RETURNED_MATERIEL_INSTOCK.getCode(), XbbRefTypeEnum.CONTRACT_OUTSTOCK.getCode(), XbbRefTypeEnum.PURCHASE_INSTOCK.getCode(), XbbRefTypeEnum.REFUND_INSTOCK.getCode(), XbbRefTypeEnum.RETURNED_PURCHASE_OUTSTOCK.getCode(),XbbRefTypeEnum.WORK_ORDER_OUTSTOCK.getCode(), XbbRefTypeEnum.PRODUCTION_MATERIEL_OUTSTOCK.getCode());
        boolean isSource = sourceTypeList.contains(businessType);
        boolean coverCostAndStock = true;
        //新建的单据
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessProductListRelyDTO.getBusinessType());
        JSONObject productObj = new JSONObject();
        JSONArray productArray = new JSONArray();
        JSONArray secondArray = new JSONArray();
        String attr = "";
        String secondAttr = "";
        String thirdAttr = "";
        String fourthAttr = "";
        String fifthAttr = "";
        String refundAmountAttr = "";
        Double otherExpense = 0D;
        Double discountAmount = 0D;
        Double discount = 1D;
        Double refundAmount = 0D;
        Map<String, LinkProductRelyEntity> linkProductRelyEntityMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<LinkProductRelyEntity> linkProductRelyEntityList = linkProductRelyModel.getByFormIdAndLinkFormId(corpid, businessProductListRelyDTO.getFormId(), businessProductListRelyDTO.getSourceFormId(), DelEnum.NORMAL.getDel());
        linkProductRelyEntityList.forEach(linkProductRelyEntity -> linkProductRelyEntityMap.put(linkProductRelyEntity.getField(), linkProductRelyEntity));
        Map<Long, JSONObject> productBusinessDataMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Object, String> refundWarehouseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, String> refUnitMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        switch (xbbRefTypeEnum){
            case INSTOCK:
            case PURCHASE_INSTOCK:
            case REFUND_INSTOCK:
            case PRODUCTION_INSTOCK:
                InstockTypeEnum instockTypeEnum = InstockTypeEnum.getByStockBusinessType(businessType);
                if (Objects.isNull(type)) {
                    type = instockTypeEnum.getCode();
                }
                List<BusinessProductEntity> businessProductEntityList = formDataValidateProductHelp.searchUnInstockProduct(corpid,refId,type, false);
                List<Long> productIdList = new ArrayList<>();
                if (!businessProductEntityList.isEmpty()) {
                    for (BusinessProductEntity businessProductEntity : businessProductEntityList) {
                        Long productId = businessProductEntity.getProductId();
                        productIdList.add(productId);
                        if (Objects.nonNull(businessProductEntity.getRefProductId())) {
                            refUnitMap.put(businessProductEntity.getRefProductId(), businessProductEntity.getProductUnit());
                        }
                    }
                }
                Map<Long,Double> costMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Map<Long,Double> stockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Map<Object,Double> refundCostMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                JSONArray warehouseObj = new JSONArray();
                if (Objects.equals(instockTypeEnum.getCode(),InstockTypeEnum.FINSHED_PRODUCT_INSTOCK.getCode())) {
                    warehouseObj = formDataValidateProductHelp.getWarehouseObj(corpid,businessProductListRelyDTO.getDataId(),instockTypeEnum.getBusinessType(),true);
                    Long warehouseId = warehouseObj.getJSONObject(0).getLong("id");
                    formDataValidateProductHelp.getSkuWarehouseCost(productIdList,warehouseId,corpid,costMap,stockMap);
                    coverCostAndStock = false;
                } else if (Objects.equals(instockTypeEnum.getCode(), InstockTypeEnum.RED_CONTRACT_INSTOCK.getCode())) {
                    // 退货退款入库取销售出库成本
                        PaasFormDataEntityExt paasFormDataEntityExt = proGetHelp.getByKey(refId, XbbRefTypeEnum.REFUND.getCode(), SaasMarkEnum.SAAS.getCode(), corpid);
                        Long contractId = paasFormDataEntityExt.getData().getLong(RefundEnum.CONTRACT_ID.getAttr());
                        Long redContractId = paasFormDataEntityExt.getData().getLong(RefundEnum.RED_CONTRACT_ID.getAttr());

                        Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        param.put("corpid",corpid);
                        param.put("del",0);
                        param.put("contractId", redContractId);
                        param.put(ParameterConstant.ORDER_BY_STR, BasicConstant.SORT);
                        List<ContractProductEntity> refundProductEntityList = contractProductModel.findEntitys(param);
                        boolean needMerge = true;
                        for (ContractProductEntity contractProductEntity : refundProductEntityList) {
                            if (Objects.nonNull(contractProductEntity.getRefProductId()) && !Objects.equals(contractProductEntity.getRefProductId(), 0)) {
                                needMerge = false;
                                break;
                            }
                        }
                        param.clear();
                        param.put("corpid", corpid);
                        param.put("del", 0);
                        param.put("refId", contractId);
                        param.put("type", OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode());
                        param.put(ParameterConstant.ORDER_BY_STR, BasicConstant.SORT);
                        List<OutstockProductEntity> outstockProductEntityList = outstockProductModel.findEntitys(param);
                        Map<Long, Double> totalCostMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        Map<Long, Double> totalNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        if (needMerge) {
                            for (OutstockProductEntity outstockProductEntity : outstockProductEntityList) {
                                Long productId = outstockProductEntity.getProductId();
                                Double extraCost = Arith.mul(outstockProductEntity.getCost(), outstockProductEntity.getProductNum());
                                if (totalCostMap.containsKey(productId)) {
                                    Double totalCost = totalCostMap.get(productId);
                                    totalCostMap.put(productId, Arith.add(totalCost, extraCost));
                                } else {
                                    totalCostMap.put(productId, extraCost);
                                }
                                if (totalNumMap.containsKey(productId)) {
                                    Double totalNum = totalNumMap.get(productId);
                                    totalNumMap.put(productId, Arith.add(totalNum, outstockProductEntity.getProductNum()));
                                } else {
                                    totalNumMap.put(productId, outstockProductEntity.getProductNum());
                                }
                            }
                        }

                        for (Long productId : productIdList) {
                            if (needMerge) {
                                if (totalCostMap.containsKey(productId) && totalNumMap.containsKey(productId) && !Objects.equals(totalNumMap.get(productId),0)) {
                                    refundCostMap.put(productId, Arith.div(totalCostMap.get(productId), totalNumMap.get(productId)));
                                }
                            } else {
                                for (ContractProductEntity refundProduct : refundProductEntityList) {
                                    if (Objects.equals(productId, refundProduct.getProductId())) {
                                        Long refProductId = refundProduct.getRefProductId();
                                        for (OutstockProductEntity outstockProductEntity : outstockProductEntityList) {
                                            if (Objects.equals(outstockProductEntity.getId(), refProductId)) {
                                                if (Objects.nonNull(outstockProductEntity.getBusinessUnit()) && Objects.nonNull(outstockProductEntity.getPriceData()) && Objects.equals(refundProduct.getBusinessUnit(), outstockProductEntity.getBusinessUnit()) && Objects.equals(Objects.toString(refundProduct.getBusinessUnit(),""), refUnitMap.get(refundProduct.getId()))) {
                                                    outstockProductEntity.setCost(outstockProductEntity.getPriceData().getDouble(SelectProductEnum.COST.getAttr()));
                                                }
                                                refundCostMap.put(productId + "_" + refundProduct.getId(), outstockProductEntity.getCost());
                                                refundWarehouseMap.put(productId + "_" + refundProduct.getId(), outstockProductEntity.getWarehouseId().toString());
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }else {
                        //其他
                        costMap = formDataValidateProductHelp.getSkuCost(productIdList,corpid);
                    }
                attr = InstockEnum.PRODUCT.getAttr();
                for (BusinessProductEntity entity : businessProductEntityList){
                    productBusinessDataMap.put(entity.getId(), entity.getData());
                    JSONObject json = new JSONObject();
                    double rate = entity.getRate() != null ? entity.getRate() : 1D;
                    json.put(BusinessConstant.BUSINESS_PRODUCT_ID, entity.getId());
                    json.put(InstockProductEnum.UNIT.getAttr(), entity.getProductUnit());
                    json.put(InstockProductEnum.PRODUCT.getAttr(),entity.getProductId());
                    json.put(InstockProductEnum.NUM.getAttr(),entity.getProductNum());
                    if (Objects.equals(instockTypeEnum.getCode(),InstockTypeEnum.FINSHED_PRODUCT_INSTOCK.getCode())) {
                        json.put(InstockProductEnum.STOCK.getAttr(), stockMap.getOrDefault(entity.getProductId(), 0D));
                        json.put(InstockProductEnum.COST.getAttr(), Arith.mul(rate, costMap.getOrDefault(entity.getProductId(), 0D)));
                    }else if (Objects.equals(instockTypeEnum.getCode(),InstockTypeEnum.RED_CONTRACT_INSTOCK.getCode())){
                        json.put(InstockProductEnum.COST.getAttr(), Arith.mul(rate, refundCostMap.getOrDefault(entity.getProductId(), 0D)));
                        if (Objects.nonNull(entity.getRefProductId())) {
                            json.put(InstockProductEnum.COST.getAttr(), Arith.mul(rate, refundCostMap.getOrDefault(entity.getProductId() + "_" + entity.getRefProductId(), 0D)));
                        }
                        json.put(RefundInstockProductEnum.PRICE.getAttr(), entity.getPrice());
                        json.put(RefundInstockProductEnum.SUBTOTAL.getAttr(), json.getDouble(RefundInstockProductEnum.NUM.getAttr()) * entity.getPrice());

                        JSONObject data = entity.getData();
                        if (Objects.nonNull(data)) {
                            json.put(InstockProductEnum.BATCH.getAttr(), data.get(InstockProductEnum.BATCH.getAttr()));
                            json.put(InstockProductEnum.GUARANTEE_PERIOD.getAttr(), data.get(InstockProductEnum.GUARANTEE_PERIOD.getAttr()));
                            json.put(InstockProductEnum.PRODUCE_DATE.getAttr(), data.get(InstockProductEnum.PRODUCE_DATE.getAttr()));
                        }
                    }else {
                        json.put(InstockProductEnum.COST.getAttr(), entity.getPrice());
                        json.put(SelectProductEnum.SOURCE_PRICE.getAttr(),entity.getPrice());
                    }
                    json.put(InstockProductEnum.TOTAL_COST.getAttr(),json.getDouble(InstockProductEnum.NUM.getAttr()) * json.getDouble(InstockProductEnum.COST.getAttr()));
                    json.put(InstockProductEnum.WAREHOUSE.getAttr(),warehouseObj);
                    json.put(OutstockProductEnum.MEMO.getAttr(),entity.getMemo());
                    if (Objects.nonNull(json.get(SelectProductEnum.PRODUCE_DATE.getAttr())) && Objects.nonNull(json.get(SelectProductEnum.GUARANTEE_PERIOD.getAttr()))) {
                        json.put(OutstockProductEnum.EXPIRE_DATE.getAttr(), json.getLong(SelectProductEnum.PRODUCE_DATE.getAttr()) + json.getLong(SelectProductEnum.GUARANTEE_PERIOD.getAttr()) * TimeConstant.SECONDS_PER_DAY);
                    }
                    if (Objects.nonNull(entity.getRefProductId())) {
                        json.put(BusinessConstant.REF_PRODUCT_ID, entity.getRefProductId());
                    }
                    productArray.add(json);
                }

                break;
            case OUTSTOCK:
            case CONTRACT_OUTSTOCK:
                ContractEntityExt contractEntityExt = contractModel.getByKey(refId, corpid);
                JSONObject contractEntityExtData = contractEntityExt.getData();
                // 优惠金额 = 合同优惠金额 - 已出库优惠金额
                String discountAmountAttr = ContractEnum.DISCOUNT_AMOUNT.getAttr();
                String outstockDiscountAmountAttr = ContractEnum.OUTSTOCK_DISCOUNT_AMOUNT.getAttr();
                if (contractEntityExtData.containsKey(discountAmountAttr)) {
                    BigDecimal outstockDiscountAmountAmount = contractEntityExtData.containsKey(outstockDiscountAmountAttr) ? contractEntityExtData.getBigDecimal(outstockDiscountAmountAttr) : BigDecimal.ZERO;
                    BigDecimal contractDiscountAmount = contractEntityExtData.getBigDecimal(discountAmountAttr).subtract(outstockDiscountAmountAmount);
                    productObj.put(ContractOutstockEnum.DISCOUNT_AMOUNT.getAttr(), contractDiscountAmount);
                }
                String otherExpenseAttr = ContractEnum.OTHER_EXPENSE.getAttr();
                String outstockOtherExpenseAttr = ContractEnum.OUTSTOCK_OTHER_EXPENSE.getAttr();
                if (contractEntityExtData.containsKey(otherExpenseAttr)) {
                    BigDecimal outstockOtherExpenseAmount = contractEntityExtData.containsKey(outstockOtherExpenseAttr) ? contractEntityExtData.getBigDecimal(outstockOtherExpenseAttr) : BigDecimal.ZERO;
                    // 其他费用 = 合同其他费用 - 已出库其他费用
                    BigDecimal contractOtherExpense = contractEntityExtData.getBigDecimal(otherExpenseAttr).subtract(outstockOtherExpenseAmount);
                    productObj.put(ContractOutstockEnum.OTHER_EXPENSE.getAttr(), contractOtherExpense);
                }
                String discountAttr = ContractEnum.DISCOUNT.getAttr();;
                if(contractEntityExtData.containsKey(discountAttr)){
                    productObj.put(ContractOutstockEnum.WHOLE_ORDE_DISCOUNT_RATE.getAttr(), contractEntityExtData.get(discountAttr));
                }
            case WORK_ORDER_OUTSTOCK:
                OutstockTypeEnum outstockTypeEnum = OutstockTypeEnum.getByStockBusinessType(businessType);
                if (Objects.isNull(type)) {
                    type = outstockTypeEnum.getCode();
                }
                businessProductEntityList = formDataValidateProductHelp.searchUnOutstockProduct(corpid,refId,type, false);
                productIdList = new ArrayList<>();
                if (!businessProductEntityList.isEmpty()) {
                    for (BusinessProductEntity businessProductEntity : businessProductEntityList) {
                        Long productId = businessProductEntity.getProductId();
                        productIdList.add(productId);
                    }
                }
                stockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                warehouseObj = new JSONArray();

                costMap = formDataValidateProductHelp.getSkuCost(productIdList,corpid);

                Map<Long,Double> priceMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                if (Objects.equals(type,OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode())){
                    priceMap = formDataValidateProductHelp.getSkuPrice(productIdList,corpid);
                }
                for (BusinessProductEntity entity : businessProductEntityList){
                    productBusinessDataMap.put(entity.getId(), entity.getData());
                    JSONObject json = new JSONObject();
                    double rate = entity.getRate() == null ? 1D : entity.getRate();
                    json.put(BusinessConstant.BUSINESS_PRODUCT_ID, entity.getId());
                    json.put(OutstockProductEnum.PRODUCT.getAttr(),entity.getProductId());
                    json.put(OutstockProductEnum.WAREHOUSE.getAttr(),warehouseObj);
                    json.put(OutstockProductEnum.COST.getAttr(), Arith.mul(rate, costMap.getOrDefault(entity.getProductId(), 0D)));
                    json.put(InstockProductEnum.UNIT.getAttr(), entity.getProductUnit());
                    json.put(InstockProductEnum.NUM.getAttr(),entity.getProductNum());
                    json.put(OutstockProductEnum.TOTAL_COST.getAttr(),json.getDouble(OutstockProductEnum.NUM.getAttr()) * json.getDouble(OutstockProductEnum.COST.getAttr()));
                    json.put(OutstockProductEnum.MEMO.getAttr(),entity.getMemo());
                    if (Objects.equals(type,OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode())) {
                        json.put(ContractOutstockProductEnum.PRICE.getAttr(), Objects.isNull(entity.getHistoricalPrice()) ? priceMap.getOrDefault(entity.getProductId(), 0D) : entity.getHistoricalPrice());
                        json.put(ContractOutstockProductEnum.SELLING_PRICE.getAttr(), entity.getPrice());
                        json.put(ContractOutstockProductEnum.DISCOUNT.getAttr(), entity.getDiscount());
                        json.put(ContractOutstockProductEnum.SUBTOTAL.getAttr(), entity.getProductNum() * entity.getPrice());
                    }
                    if (Objects.nonNull(entity.getRefProductId())) {
                        json.put(BusinessConstant.REF_PRODUCT_ID, entity.getRefProductId());
                    }
                    productArray.add(json);
                }
                attr = OutstockEnum.PRODUCT.getAttr();
                break;
            case RETURNED_PURCHASE_OUTSTOCK:
            case PRODUCTION_MATERIEL_OUTSTOCK:
                outstockTypeEnum = OutstockTypeEnum.getByStockBusinessType(businessType);
                if (Objects.isNull(type)) {
                    type = outstockTypeEnum.getCode();
                }
                Map<Object,Double> returnPurchasecostMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Map<Object,Double> returnPurchasestockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                businessProductEntityList = formDataValidateProductHelp.searchUnOutstockProduct(corpid,refId,type, false);
                List<Long> warehouseNameSet = new ArrayList<>();
                if (!businessProductEntityList.isEmpty()) {
                    for (BusinessProductEntity entity : businessProductEntityList) {
                        productBusinessDataMap.put(entity.getId(), entity.getData());
                        JSONObject json = new JSONObject();
                        json.put(BusinessConstant.BUSINESS_PRODUCT_ID, entity.getId());
                        json.put(MultiUnitConstant.RATE, entity.getRate());
                        json.put(OutstockProductEnum.PRODUCT.getAttr(),entity.getProductId());
                        json.put(SelectProductEnum.SOURCE_PRICE.getAttr(), entity.getPrice());
                        json.put(InstockProductEnum.UNIT.getAttr(), entity.getProductUnit());
                        json.put(InstockProductEnum.NUM.getAttr(),entity.getProductNum());
                        json.put(OutstockProductEnum.MEMO.getAttr(),entity.getMemo());
                        if (Objects.equals(businessType, XbbRefTypeEnum.PRODUCTION_MATERIEL_OUTSTOCK.getCode())) {
                            json.put(OutstockProductEnum.WAREHOUSE.getAttr(), entity.getWarehouseId());
                            warehouseNameSet.add(entity.getWarehouseId());
                            coverCostAndStock = false;
                        }else {
                            json.put(OutstockProductEnum.COST.getAttr(), entity.getCost());
                            json.put(OutstockProductEnum.TOTAL_COST.getAttr(), json.getDouble(OutstockProductEnum.NUM.getAttr()) * json.getDouble(OutstockProductEnum.COST.getAttr()));
                            JSONObject data = entity.getData();
                            if (Objects.nonNull(data) && Objects.nonNull(data.getLong(SelectProductEnum.WAREHOUSE.getAttr()))) {
                                warehouseNameSet.add(data.getLong(SelectProductEnum.WAREHOUSE.getAttr()));
                                json.put(OutstockProductEnum.WAREHOUSE.getAttr(), data.getLong(SelectProductEnum.WAREHOUSE.getAttr()));

                                json.put(OutstockProductEnum.BATCH.getAttr(), data.getString(OutstockProductEnum.BATCH.getAttr()));
                                json.put(OutstockProductEnum.GUARANTEE_PERIOD.getAttr(), data.getLong(OutstockProductEnum.GUARANTEE_PERIOD.getAttr()));
                                json.put(OutstockProductEnum.PRODUCE_DATE.getAttr(), data.getLong(OutstockProductEnum.PRODUCE_DATE.getAttr()));
                                if (Objects.nonNull(json.get(SelectProductEnum.PRODUCE_DATE.getAttr())) && Objects.nonNull(json.get(SelectProductEnum.GUARANTEE_PERIOD.getAttr()))) {
                                    json.put(OutstockProductEnum.EXPIRE_DATE.getAttr(), json.getLong(SelectProductEnum.PRODUCE_DATE.getAttr()) + json.getLong(SelectProductEnum.GUARANTEE_PERIOD.getAttr()) * TimeConstant.SECONDS_PER_DAY);
                                }
                            }
                        }
                        if (Objects.nonNull(entity.getRefProductId())) {
                            json.put(BusinessConstant.REF_PRODUCT_ID, entity.getRefProductId());
                        }
                        productArray.add(json);
                    }
                }

                Map<Long, JSONObject> warehouseObjMapByIdIn = warehouseModel.findWarehouseObjMapByIdIn(warehouseNameSet, corpid);

                formDataValidateProductHelp.getSkuWarehouseOrBatchCost(productArray, corpid, returnPurchasecostMap, returnPurchasestockMap);
                for (int i = 0;i < productArray.size();i++) {
                    JSONObject jsonObject = productArray.getJSONObject(i);
                    double rate = Objects.nonNull(jsonObject.getDouble(MultiUnitConstant.RATE)) ? jsonObject.getDouble(MultiUnitConstant.RATE) : 1D;
                    if (Objects.nonNull(jsonObject.getLong(SelectProductEnum.WAREHOUSE.getAttr()))) {
                        Long warehouseId = jsonObject.getLong(SelectProductEnum.WAREHOUSE.getAttr());
                        String batch = jsonObject.getString(OutstockProductEnum.BATCH.getAttr());
                        //分为取批次成本丶库存和分仓成本丶库存
                        Object key;
                        if (StringUtil.isNotEmpty(batch)) {
                            key = formDataValidateProductHelp.getBatchKey(jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr()), warehouseId, batch, jsonObject.getLong(SelectProductEnum.PRODUCE_DATE.getAttr()), FastJsonHelper.getLongOrDefaultFromFormData(jsonObject, SelectProductEnum.GUARANTEE_PERIOD.getAttr(), 0L) * TimeConstant.SECONDS_PER_DAY);
                        }else {
                            key = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr()) + "_" + warehouseId;
                        }
                        jsonObject.put(SelectProductEnum.STOCK.getAttr(), returnPurchasestockMap.getOrDefault(key, 0D));
                        if (Objects.equals(businessType, XbbRefTypeEnum.PRODUCTION_MATERIEL_OUTSTOCK.getCode())) {
                            jsonObject.put(SelectProductEnum.COST.getAttr(), Arith.mul(rate, returnPurchasecostMap.getOrDefault(key, 0D)));
                        }
                        JSONArray returnPurchaseWarehouseObj = new JSONArray();
                        JSONObject returnWarehouseObj = new JSONObject();
                        returnWarehouseObj.put("id", warehouseId);
                        returnWarehouseObj.put("name", warehouseObjMapByIdIn.getOrDefault(warehouseId, new JSONObject()).get(StringConstant.VALUE));
                        returnPurchaseWarehouseObj.add(returnWarehouseObj);
                        jsonObject.put(OutstockProductEnum.WAREHOUSE.getAttr(), returnPurchaseWarehouseObj);
                        JSONObject batchObj = new JSONObject();
                        batchObj.put("text", batch);
                        batchObj.put("value", batch);
                        jsonObject.put(OutstockProductEnum.BATCH.getAttr(), batchObj);
                    }
                }
                attr = OutstockEnum.PRODUCT.getAttr();
                break;
            case PRODUCTION_ORDER:
                Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put("corpid",corpid);
                param.put("bomId",refId);
                param.put("del",0);
                param.put(ParameterConstant.ORDER_BY_STR, BasicConstant.SORT);
                // BOM版本
                BomBillEntityExt bomBillEntityExt = bomBillModel.getByKey(refId, corpid);
                if (Objects.nonNull(bomBillEntityExt)) {
                    String bomVersion = bomBillEntityExt.getData().getString(BomBillEnum.VERSION.getAttr());
                    productObj.put(ProductionOrderEnum.BOM_VERSION.getAttr(), bomVersion);
                }
                List<BomProductEntity> bomProductEntityList = bomProductModel.findEntitys(param);
                for (BomProductEntity entity : bomProductEntityList){
                    productBusinessDataMap.put(entity.getId(), entity.getData());
                    JSONObject json = new JSONObject();
                    json.put(BusinessConstant.BUSINESS_PRODUCT_ID, entity.getId());
                    if (Objects.equals(entity.getType(),1)){
                        json.put(ProductionOrderFinishProductEnum.PRODUCT.getAttr(),entity.getProductId());
                        json.put(ProductionOrderFinishProductEnum.NUM.getAttr(),entity.getProductNum());
                        json.put(ProductionOrderFinishProductEnum.UNIT.getAttr(),entity.getProductUnit());
                        json.put(ProductionOrderFinishProductEnum.MEMO.getAttr(),entity.getMemo());
                        json.put("unitNum", entity.getProductNum());
                        productArray.add(json);
                    }else {
                        json.put(ProductionOrderMaterielProductEnum.PRODUCT.getAttr(),entity.getProductId());
                        json.put(ProductionOrderMaterielProductEnum.NUM.getAttr(),entity.getProductNum());
                        json.put(ProductionOrderMaterielProductEnum.LOSS_RATE.getAttr(),entity.getAttritionRate());
                        json.put(ProductionOrderFinishProductEnum.UNIT.getAttr(),entity.getProductUnit());
                        json.put(ProductionOrderMaterielProductEnum.MEMO.getAttr(),entity.getMemo());
                        json.put("unitNum", entity.getProductNum());
                        secondArray.add(json);
                    }
                }
                attr = ProductionOrderEnum.PRODUCT.getAttr();
                secondAttr = ProductionOrderEnum.MATERIEL.getAttr();
                break;
            case CONTRACT:
                if (Objects.equals(businessProductListRelyDTO.getRefBusinessType(),XbbRefTypeEnum.SALES_OPPORTUNITY.getCode())){
                    param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    param.put("corpid",corpid);
                    param.put("opportunityId",refId);
                    param.put("del",0);
                    param.put(ParameterConstant.ORDER_BY_STR, BasicConstant.SORT);
                    List<OpportunityProductEntity> opportunityProductEntityList1 = opportunityProductModel.findEntitys(param);
                    for (OpportunityProductEntity entity : opportunityProductEntityList1){
                        productBusinessDataMap.put(entity.getId(), entity.getData());
                        JSONObject json = new JSONObject();
                        json.put(BusinessConstant.BUSINESS_PRODUCT_ID, entity.getId());
                        json.put(ContractProductEnum.PRODUCT.getAttr(),entity.getProductId());
                        json.put(ContractProductEnum.PRICE.getAttr(), entity.getHistoricalPrice());
                        json.put(ContractProductEnum.DISCOUNT.getAttr(), entity.getDiscount());
                        json.put(ContractProductEnum.SELLING_PRICE.getAttr(), entity.getPrice());
                        json.put(ContractProductEnum.MEMO.getAttr(), entity.getMemo());
                        if (Objects.nonNull(entity.getBusinessUnit())) {
                            json.put(InstockProductEnum.UNIT.getAttr(), entity.getBusinessUnit());
                            json.put(InstockProductEnum.NUM.getAttr(),entity.getBusinessNum());
                            if (Objects.nonNull(entity.getPriceData())) {
                                json.put(ContractProductEnum.PRICE.getAttr(), entity.getPriceData().get(SelectProductEnum.PRICE.getAttr()));
                                json.put(ContractProductEnum.SELLING_PRICE.getAttr(), entity.getPriceData().get(SelectProductEnum.SELLING_PRICE.getAttr()));
                            }
                        } else {
                            json.put(InstockProductEnum.UNIT.getAttr(), entity.getProductUnit());
                            json.put(InstockProductEnum.NUM.getAttr(),entity.getProductNum());
                        }
                        json.put(ContractProductEnum.SUBTOTAL.getAttr(), entity.getProductNum() * entity.getPrice());
                        productArray.add(json);
                    }
                }else {
                    param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    param.put("corpid",corpid);
                    param.put("quotationId",refId);
                    param.put("del",0);
                    param.put(ParameterConstant.ORDER_BY_STR, BasicConstant.SORT);
                    List<QuotationProductEntity> quotationProductEntityList = quotationProductModel.findEntitys(param);
                    QuotationEntityExt quotationEntityExt = quotationModel.getByKey(refId, corpid);
                    if (Objects.nonNull(quotationEntityExt)) {
                        JSONObject data = quotationEntityExt.getData();
                        otherExpense = getDoubleOrDefaultFromFormData(data, QuotationEnum.OTHER_EXPENSE.getAttr(), 0D);
                        discountAmount = getDoubleOrDefaultFromFormData(data, QuotationEnum.DISCOUNT_AMOUNT.getAttr(), 0D);
                        discount = getDoubleOrDefaultFromFormData(data, QuotationEnum.DISCOUNT.getAttr(), 1D);
                    }
                    for (QuotationProductEntity entity : quotationProductEntityList){
                        productBusinessDataMap.put(entity.getId(), entity.getData());
                        JSONObject json = new JSONObject();
                        json.put(BusinessConstant.BUSINESS_PRODUCT_ID, entity.getId());
                        json.put(ContractProductEnum.PRODUCT.getAttr(),entity.getProductId());
                        json.put(ContractProductEnum.PRICE.getAttr(), entity.getHistoricalPrice());
                        json.put(ContractProductEnum.DISCOUNT.getAttr(), entity.getDiscount());
                        json.put(ContractProductEnum.SELLING_PRICE.getAttr(), entity.getPrice());
                        json.put(ContractProductEnum.MEMO.getAttr(), entity.getMemo());
                        if (Objects.nonNull(entity.getBusinessUnit())) {
                            json.put(InstockProductEnum.UNIT.getAttr(), entity.getBusinessUnit());
                            json.put(InstockProductEnum.NUM.getAttr(),entity.getBusinessNum());
                            if (Objects.nonNull(entity.getPriceData())) {
                                json.put(ContractProductEnum.PRICE.getAttr(), entity.getPriceData().get(SelectProductEnum.PRICE.getAttr()));
                                json.put(ContractProductEnum.SELLING_PRICE.getAttr(), entity.getPriceData().get(SelectProductEnum.SELLING_PRICE.getAttr()));
                            }
                        } else {
                            json.put(InstockProductEnum.UNIT.getAttr(), entity.getProductUnit());
                            json.put(InstockProductEnum.NUM.getAttr(),entity.getProductNum());
                        }
                        json.put(ContractProductEnum.SUBTOTAL.getAttr(), entity.getProductNum() * entity.getPrice());
                        productArray.add(json);
                    }
                }
                attr = ContractEnum.PRODUCT.getAttr();
                thirdAttr = ContractEnum.OTHER_EXPENSE.getAttr();
                fourthAttr = ContractEnum.DISCOUNT_AMOUNT.getAttr();
                fifthAttr = ContractEnum.DISCOUNT.getAttr();
                break;
            case QUOTATION:
                param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put("corpid",corpid);
                param.put("opportunityId",refId);
                param.put("del",0);
                param.put(ParameterConstant.ORDER_BY_STR, BasicConstant.SORT);
                List<OpportunityProductEntity> opportunityProductEntityList1 = opportunityProductModel.findEntitys(param);
                for (OpportunityProductEntity entity : opportunityProductEntityList1){
                    productBusinessDataMap.put(entity.getId(), entity.getData());
                    JSONObject json = new JSONObject();
                    json.put(BusinessConstant.BUSINESS_PRODUCT_ID, entity.getId());
                    json.put(QuotationProductEnum.PRODUCT.getAttr(),entity.getProductId());
                    json.put(QuotationProductEnum.UNIT.getAttr(), entity.getProductUnit());
                    json.put(QuotationProductEnum.PRICE.getAttr(), entity.getHistoricalPrice());
                    json.put(QuotationProductEnum.DISCOUNT.getAttr(), entity.getDiscount());
                    json.put(QuotationProductEnum.SELLING_PRICE.getAttr(), entity.getPrice());
                    json.put(QuotationProductEnum.MEMO.getAttr(), entity.getMemo());
                    if (Objects.nonNull(entity.getBusinessUnit())) {
                        json.put(InstockProductEnum.UNIT.getAttr(), entity.getBusinessUnit());
                        json.put(InstockProductEnum.NUM.getAttr(),entity.getBusinessNum());
                        if (Objects.nonNull(entity.getPriceData())) {
                            json.put(ContractProductEnum.PRICE.getAttr(), entity.getPriceData().get(SelectProductEnum.PRICE.getAttr()));
                            json.put(ContractProductEnum.SELLING_PRICE.getAttr(), entity.getPriceData().get(SelectProductEnum.SELLING_PRICE.getAttr()));
                        }
                    } else {
                        json.put(InstockProductEnum.UNIT.getAttr(), entity.getProductUnit());
                        json.put(InstockProductEnum.NUM.getAttr(),entity.getProductNum());
                    }
                    json.put(QuotationProductEnum.SUBTOTAL.getAttr(), entity.getProductNum() * entity.getPrice());
                    productArray.add(json);
                }
                attr = QuotationEnum.PRODUCT.getAttr();
                break;
            default:
                break;
        }

        Map<Long,Map<String,JSONObject>> productMaps = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<Long> productIdList = new ArrayList<>();
        Map<Long, MultiUnitItemPoJo> groupBaseUnitMap = relativeProductHelp.getGroupBaseUnitMap(corpid);
        if (!productArray.isEmpty() || !secondArray.isEmpty()) {
            for (int i = 0; i < productArray.size(); i++) {
                JSONObject jsonObject = productArray.getJSONObject(i);
                productIdList.add(jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr()));
            }
            for (int i = 0;i < secondArray.size();i++){
                JSONObject jsonObject = secondArray.getJSONObject(i);
                productIdList.add(jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr()));
            }
            productMaps = formDataValidateProductHelp.getWarehouseMap(productIdList,corpid);
        }
        // 源单解释
        Map<String, FieldAttrEntity> sourceExplainMap = null;
        // 当前表单解释
        Map<String, FieldAttrEntity> thisExplainMap = null;
        UserAndDepartmentGetDTO userAndDepartmentGetDTO = new UserAndDepartmentGetDTO();
        BeanUtil.copyProperties(businessProductListRelyDTO, userAndDepartmentGetDTO);
        UserAndDepartmentGetVO userAndDepartmentGetVO = userHelp.getUserDepartmentMap(userAndDepartmentGetDTO);
        Map<String, UserEntity> userMap = userAndDepartmentGetVO.getUserMap();
        Map<String, DepartmentEntity> departmentMap = userAndDepartmentGetVO.getDepartmentMap();
        if (!productArray.isEmpty()){
            LinkProductRelyEntity linkProductRelyEntity = linkProductRelyEntityMap.get(attr);
            // 当前表单某个关联产品解释
            Map<String, FieldAttrEntity> subThisExplainMap = null;
            // 源单某个关联产品解释
            Map<String, FieldAttrEntity> subSourceExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 当前表单某个关联产品子字段与源单某个关联产品对应关系
            Map<String, String> thisToTarget = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (Objects.nonNull(linkProductRelyEntity)) {
                // 源数据表单
                PaasFormExplainEntity paasFormExplainEntity = proFormHelp.getExplainEntity(corpid, linkProductRelyEntity.getSourceFormId(), linkProductRelyEntity.getSourceBusinessType());
                List<FieldAttrEntity>  explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
                sourceExplainMap = ExplainUtil.getExplainMapByList(explainList, null);
                // 当前表单解释
                PaasFormExplainEntity displayFormExplain = proFormHelp.getExplainEntity(corpid, linkProductRelyEntity.getFormId(), linkProductRelyEntity.getBusinessType());
                thisExplainMap = ExplainUtil.getExplainMap(displayFormExplain.getExplains(), null);
                subThisExplainMap = getProductRelyMap(attr, linkProductRelyEntity, sourceExplainMap, thisExplainMap, subSourceExplainMap, thisToTarget);
            }
            Boolean costField = true;
            if (Objects.equals(XbbRefTypeEnum.PURCHASE.getCode(),businessProductListRelyDTO.getBusinessType())){
                costField = formDataValidateProductHelp.productCostVisible(corpid,businessProductListRelyDTO.getLoginUser());
            }
            Map<Long,PaasFormDataEntityExt> productMap = formDataValidateProductHelp.product2saveMap(corpid,productArray);
            productMap.forEach((key, value) -> {
                value.getData().put(ProductEnum.ENABLE_BATCH_SHELF_LIFE.getSaasAttr(), value.getData().getLongValue(ProductEnum.ENABLE_BATCH_SHELF_LIFE.getAttr()));
                value.getData().put(ProductEnum.ENABLE_SERIAL_NUMBER.getSaasAttr(), value.getData().getLongValue(ProductEnum.ENABLE_SERIAL_NUMBER.getAttr()));
                value.getData().put(ProductEnum.SHELF_LIFE_DAYS.getSaasAttr(), StringUtil.isEmpty(value.getData().getString(ProductEnum.SHELF_LIFE_DAYS.getAttr())) ? 0 : 1);
            });
            List<Integer> enableSerialType = Arrays.asList(XbbRefTypeEnum.OTHER_INSTOCK.getCode(), XbbRefTypeEnum.REFUND_INSTOCK.getCode(), XbbRefTypeEnum.RETURNED_MATERIEL_INSTOCK.getCode(), XbbRefTypeEnum.PURCHASE_INSTOCK.getCode(), XbbRefTypeEnum.PRODUCTION_INSTOCK.getCode(),XbbRefTypeEnum.CONTRACT_OUTSTOCK.getCode(), XbbRefTypeEnum.PRODUCTION_MATERIEL_OUTSTOCK.getCode(), XbbRefTypeEnum.OTHER_OUTSTOCK.getCode(), XbbRefTypeEnum.WORK_ORDER_OUTSTOCK.getCode(), XbbRefTypeEnum.RETURNED_PURCHASE_OUTSTOCK.getCode());
            Map<Long, List<MultiUnitPricePoJo>> priceMap = productUnitPriceModel.getPriceMapByProductIdSet(corpid, productMap.keySet());
            for (int i = 0;i < productArray.size();i++){
                JSONObject sellingMap = new JSONObject();
                JSONObject jsonObject = productArray.getJSONObject(i);
                Long productId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
                jsonObject.put(SelectProductEnum.UNIT.getAttr(), formDataValidateProductHelp.formatUnit(corpid,jsonObject.getString(SelectProductEnum.UNIT.getAttr())));
                if (productMap.isEmpty()){
                    continue;
                }
                // 产品信息
                PaasFormDataEntityExt paasFormDataEntityExt = productMap.get(productId);
                PaasFormDataEntityExt formDataEntityExt = (PaasFormDataEntityExt)CloneUtil.deepClone(paasFormDataEntityExt);
                JSONObject originData = formDataEntityExt.getData();
                // 多单位
                Integer enableMultiUnit = getIntegerOrDefaultFromFormData(originData, ProductEnum.ENABLE_MULTI_UNIT.getAttr(), 0);
                Integer enableSerial = getIntegerOrDefaultFromFormData(originData, ProductEnum.ENABLE_SERIAL_NUMBER.getAttr(), 0);
                JSONObject unitObj = FastJsonHelper.getJsonObjectOrDefaultFromFormData(jsonObject, SelectProductEnum.UNIT.getAttr(), new JSONObject());
                if (Objects.equals(1, enableMultiUnit)) {
                    MultiUnitItemPoJo multiUnitItemPoJo = groupBaseUnitMap.getOrDefault(originData.getLong(ProductEnum.UNIT.getAttr()), new MultiUnitItemPoJo());
                    // 是多单位，但是是单单位的value，或没有值，补成基本单位
                    if (unitObj.isEmpty() || !StringUtil.isDigital(unitObj.getString(StringConstant.VALUE)) || unitObj.getLong(StringConstant.VALUE) < ProductConstant.MAX_SINGLE_UNIT_VALUE) {
                        unitObj.put(MultiUnitConstant.MULTI_UNIT_TEXT, multiUnitItemPoJo.getBaseName());
                        unitObj.put(MultiUnitConstant.VALUE, multiUnitItemPoJo.getBaseValue());
                        jsonObject.put(SelectProductEnum.UNIT.getAttr(), unitObj);
                    }
                    Long unitValue = unitObj.getLong(StringConstant.VALUE);
                    List<UnitItemPoJo> itemDataPoJoList = multiUnitItemPoJo.getItemDataPoJoList();
                    List<UnitItemPoJo> copyItemPojo = (List<UnitItemPoJo>)CloneUtil.deepClone(itemDataPoJoList);
                    originData.put(ProductConstant.TRANSFORM_UNIT_RATE, itemDataPoJoList);
                    jsonObject.put(ProductConstant.TRANSFORM_UNIT_RATE, itemDataPoJoList);
                    Map<Long, UnitItemPoJo> businessUnitMap = itemDataPoJoList.stream().collect(Collectors.toMap(UnitItemPoJo::getValue, data -> data));
                    if (!ProductConstant.NO_LINK_BUSINESS_TYPE_LIST.contains(businessType)) {
                        copyItemPojo.removeIf(item -> !(Objects.equals(item.getValue(), unitValue) || Objects.equals(item.getIsBase(), 1)));
                    }
                    originData.put(ProductConstant.UNIT_RATE, copyItemPojo);
                    jsonObject.put(ProductConstant.UNIT_RATE, copyItemPojo);
                    boolean otherInOutStock = Objects.equals(businessType, XbbRefTypeEnum.INSTOCK.getCode()) || (Objects.equals(businessType, XbbRefTypeEnum.OUTSTOCK.getCode()) );
                    if (StockConstant.MULTI_UNIT_TYPE_LIST.contains(businessType) && !(StockConstant.SERIAL_TYPE_LIST.contains(businessType) && Objects.equals(enableSerial, 1)) && !otherInOutStock) {
                        // 是多单位业务类型而且不是（既开启序列号且是序列号业务类型）
                        if (StockConstant.MULTI_UNIT_PRICE_TYPE_LIST.contains(businessType)) {
                            originData.put(ProductConstant.PRICE, priceMap.get(productId));
                            jsonObject.put(ProductConstant.PRICE, priceMap.get(productId));
                        }
                        jsonObject.forEach((key,value)->{
                            if (ProductConstant.MULTI_PRICE_ATTR_LIST.contains(key)) {
                                sellingMap.put(key, value);
                            }
                        });
                        jsonObject.put(ProductConstant.SELLING_PRICE_MAP, sellingMap);
                        originData.put(ProductEnum.ENABLE_MULTI_UNIT.getSaasAttr(), 1);
                        jsonObject.put(ProductEnum.ENABLE_MULTI_UNIT.getSaasAttr(), 1);
                    } else {
                        // 不是多单位业务类型，或者是（序列号产品且是序列号业务类型）,此时不能选单位，只能是基本单位
                        if (!otherInOutStock) {
                            originData.put(SelectProductEnum.NUM.getAttr(), Arith.mul(jsonObject.getDouble(SelectProductEnum.NUM.getAttr()), Objects.isNull(businessUnitMap.getOrDefault(unitValue, new UnitItemPoJo()).getRate()) ? 1D : businessUnitMap.getOrDefault(unitValue, new UnitItemPoJo()).getRate()));
                            unitObj.put(MultiUnitConstant.MULTI_UNIT_TEXT, multiUnitItemPoJo.getBaseName());
                            unitObj.put(MultiUnitConstant.VALUE, multiUnitItemPoJo.getBaseValue());
                            originData.put(SelectProductEnum.UNIT.getAttr(), unitObj);
                        }
                        originData.put(ProductEnum.ENABLE_MULTI_UNIT.getSaasAttr(), 0);
                        jsonObject.put(ProductEnum.ENABLE_MULTI_UNIT.getSaasAttr(), 0);
                    }
                    originData.put(ProductEnum.UNIT.getAttr(), unitObj);
                } else {
                    originData.put(ProductEnum.ENABLE_MULTI_UNIT.getSaasAttr(), 0);
                    jsonObject.put(ProductEnum.ENABLE_MULTI_UNIT.getSaasAttr(), 0);
                }
                productService.setChildSpecification(Collections.singletonList(formDataEntityExt),corpid);
                JSONObject productData = new JSONObject();
                if (Objects.equals(XbbRefTypeEnum.PURCHASE.getCode(),businessProductListRelyDTO.getBusinessType())){
                    if (!costField){
                        originData.put(PurchaseProductEnum.PURCHASE_PRICE.getAttr(),0D);
                    }
                }
                originData.put(FieldTypeEnum.SERIALNO.getAlias(),paasFormDataEntityExt.getSerialNo());
                originData.put("warehouse",productMaps.get(productId));
                productData.put("sourceData", originData);
                JSONObject data = (JSONObject)originData.clone();
                if (!thisToTarget.isEmpty()) {
                    Long businessProductId = jsonObject.getLong(BusinessConstant.BUSINESS_PRODUCT_ID);
                    JSONObject productBusinessData = productBusinessDataMap.get(businessProductId);
                    ParseSingleRowDataDTO parseSingleRowDataDTO = new ParseSingleRowDataDTO();
                    BeanUtil.copyProperties(businessProductListRelyDTO, parseSingleRowDataDTO);
                   // parseSingleRowDataDTO.setCreatorId(paasFormDataEntityExt.getCreatorId());
                    parseSingleRowDataDTO.setDataJsonObject(productBusinessData);
                    parseSingleRowDataDTO.setUserMap(userMap);
                    parseSingleRowDataDTO.setDepartmentMap(departmentMap);
                    parseSingleRowDataDTO.setExplainMap(subSourceExplainMap);
                    ParseSingleRowDataVO parseSingleRowDataVO = formDataUpdateGetAnalysisDataHelp.parseSingleRowData(parseSingleRowDataDTO);
                    if(Objects.isNull(parseSingleRowDataVO)){
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PARSE_SINGLE_ROW_DATA_FAILED);
                    }
                    JSONObject result = parseSingleRowDataVO.getResult();
                    JSONObject thisData = formatThisFormData(subThisExplainMap, thisToTarget, result);
                    jsonObject.putAll(thisData);
                }
                Long refProductId = jsonObject.getLong(BusinessConstant.REF_PRODUCT_ID);
                productData.put("data",data);
                if (coverCostAndStock){
                    data.put(ProductEnum.COST.getAttr(),jsonObject.getDouble(SelectProductEnum.COST.getAttr()));
                    data.put(SelectProductEnum.SOURCE_PRICE.getAttr(),jsonObject.getDouble(SelectProductEnum.COST.getAttr()));
                    if (Objects.isNull(jsonObject.get(SelectProductEnum.STOCK.getAttr()))) {
                        jsonObject.put(SelectProductEnum.STOCK.getAttr(),data.getDouble(ProductEnum.STOCK.getAttr()));
                    }
                    if (Objects.equals(businessType, XbbRefTypeEnum.CONTRACT_OUTSTOCK.getCode())) {
                        data.put(SelectProductEnum.SOURCE_PRICE.getAttr(),jsonObject.getDouble(ContractOutstockProductEnum.SELLING_PRICE.getAttr()));
                    }else if (Objects.equals(businessType, XbbRefTypeEnum.REFUND_INSTOCK.getCode())){
                        data.put(SelectProductEnum.SOURCE_PRICE.getAttr(),jsonObject.getDouble(RefundProductEnum.PRICE.getAttr()));
                        Map<String, JSONObject> warehouseMap = productMaps.getOrDefault(productId, new HashMap<>());
                        String refundWarehouseId = refundWarehouseMap.getOrDefault(productId + "_" + jsonObject.get(BusinessConstant.REF_PRODUCT_ID), "");
                        JSONArray warehouseObj = new JSONArray();
                        JSONObject refundWarehouseObj = new JSONObject();
                        refundWarehouseObj.put("id", refundWarehouseId);
                        refundWarehouseObj.put("name", warehouseMap.getOrDefault(refundWarehouseId, new JSONObject()).getString(ProductEnum.WAREHOUSE.getSaasAttr()));
                        warehouseObj.add(refundWarehouseObj);
                        jsonObject.put(InstockProductEnum.WAREHOUSE.getAttr(), warehouseObj);
                    }
                }
                productData.put("dataId",productId);
                // 前端需要
                if (Objects.nonNull(refProductId) && isSource) {
                    productData.put("id",refProductId);
                } else {
                    productData.put("id",productId);
                }
                jsonObject.put(SelectProductEnum.PRODUCT.getAttr(),productData);
                jsonObject.put(BusinessConstant.PRODUCT_SUB_ID,0);
                if (enableSerialType.contains(businessType)) {
                    jsonObject.put(ProductEnum.ENABLE_SERIAL_NUMBER.getSaasAttr(), data.getLongValue(ProductEnum.ENABLE_SERIAL_NUMBER.getAttr()));
//                    if (BasicConstant.ONE.equals(data.getInteger(ProductEnum.ENABLE_SERIAL_NUMBER.getAttr()))) {
//                        jsonObject.put(SelectProductEnum.NUM.getAttr(), null);
//                    }
                    Integer enableBatch = getIntegerOrDefaultFromFormData(data, ProductEnum.ENABLE_BATCH_SHELF_LIFE.getAttr(), 0);
                    jsonObject.put(ProductEnum.ENABLE_BATCH_SHELF_LIFE.getSaasAttr(), enableBatch);
                    if (Objects.equals(enableBatch, EnableEnum.CLOSE.getCode())) {
                        jsonObject.put(ProductEnum.SHELF_LIFE_DAYS.getSaasAttr(), EnableEnum.CLOSE.getCode());
                        jsonObject.remove(SelectProductEnum.BATCH.getAttr());
                        jsonObject.remove(SelectProductEnum.GUARANTEE_PERIOD.getAttr());
                        jsonObject.remove(SelectProductEnum.PRODUCE_DATE.getAttr());
                        jsonObject.remove(SelectProductEnum.EXPIRE_DATE.getAttr());
                    }else {
                        if (StringUtil.isEmpty(data.getString(ProductEnum.SHELF_LIFE_DAYS.getAttr()))) {
                            jsonObject.put(ProductEnum.SHELF_LIFE_DAYS.getSaasAttr(), EnableEnum.CLOSE.getCode());
                            jsonObject.remove(SelectProductEnum.GUARANTEE_PERIOD.getAttr());
                            jsonObject.remove(SelectProductEnum.PRODUCE_DATE.getAttr());
                            jsonObject.remove(SelectProductEnum.EXPIRE_DATE.getAttr());
                        }else {
                            jsonObject.put(ProductEnum.SHELF_LIFE_DAYS.getSaasAttr(), EnableEnum.OPEN.getCode());
                            if (Objects.isNull(jsonObject.get(SelectProductEnum.GUARANTEE_PERIOD.getAttr()))) {
                                jsonObject.put(SelectProductEnum.GUARANTEE_PERIOD.getAttr(), data.get(ProductEnum.SHELF_LIFE_DAYS.getAttr()));
                                jsonObject.put(SelectProductEnum.PRODUCE_DATE.getAttr(), DateTimeUtil.getTodayInt());
                                jsonObject.put(SelectProductEnum.EXPIRE_DATE.getAttr(), DateTimeUtil.getTodayInt() + data.getLong(ProductEnum.SHELF_LIFE_DAYS.getAttr()) * TimeConstant.SECONDS_PER_DAY);
                            }
                        }
                    }
                }
            }
            formDataValidateProductHelp.loyalToProduct(productArray,corpid,businessProductListRelyDTO.getLoginUser());
            // 开启序列号的产品在getRely接口，数量必须置为null
            for (int i = 0;i < productArray.size();i++) {
                JSONObject jsonObject = productArray.getJSONObject(i);
                if (StockConstant.SERIAL_TYPE_LIST.contains(businessType)) {
                    if (BasicConstant.ONE.equals(jsonObject.getInteger((ProductEnum.ENABLE_SERIAL_NUMBER.getSaasAttr())))) {
                        jsonObject.put(SelectProductEnum.NUM.getAttr(), null);
                    }
                }
            }
        }
        if (!secondArray.isEmpty()){
            LinkProductRelyEntity secondLinkProductRelyEntity = linkProductRelyEntityMap.get(secondAttr);
            // 当前表单某个关联产品解释
            Map<String, FieldAttrEntity> subThisExplainMap = null;
            // 源单某个关联产品解释
            Map<String, FieldAttrEntity> subSourceExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 当前表单某个关联产品子字段与源单某个关联产品对应关系
            Map<String, String> thisToTarget = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (Objects.nonNull(secondLinkProductRelyEntity)) {
                if (Objects.isNull(sourceExplainMap)) {
                    // 源数据表单
                    PaasFormExplainEntity paasFormExplainEntity = proFormHelp.getExplainEntity(corpid, secondLinkProductRelyEntity.getSourceFormId(), secondLinkProductRelyEntity.getSourceBusinessType());
                    List<FieldAttrEntity>  explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
                    sourceExplainMap = ExplainUtil.getExplainMapByList(explainList, null);
                }
                if (Objects.isNull(thisExplainMap)) {
                    // 当前表单解释
                    PaasFormExplainEntity displayFormExplain = proFormHelp.getExplainEntity(corpid, secondLinkProductRelyEntity.getFormId(), secondLinkProductRelyEntity.getBusinessType());
                    thisExplainMap = ExplainUtil.getExplainMap(displayFormExplain.getExplains(), null);
                }
                subThisExplainMap = getProductRelyMap(secondAttr, secondLinkProductRelyEntity, sourceExplainMap, thisExplainMap, subSourceExplainMap, thisToTarget);
            }
            Map<Long,PaasFormDataEntityExt> productMap = formDataValidateProductHelp.product2saveMap(corpid,secondArray);
            for (int i = 0;i < secondArray.size();i++){
                JSONObject jsonObject = secondArray.getJSONObject(i);
                Long productId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
                jsonObject.put(SelectProductEnum.UNIT.getAttr(), formDataValidateProductHelp.formatUnit(corpid,jsonObject.getString(SelectProductEnum.UNIT.getAttr())));
                PaasFormDataEntityExt paasFormDataEntityExt = productMap.get(productId);
                if(Objects.isNull(paasFormDataEntityExt)){
                    continue;
                }
                PaasFormDataEntityExt formDataEntityExt = (PaasFormDataEntityExt)CloneUtil.deepClone(paasFormDataEntityExt);
                JSONObject originData = formDataEntityExt.getData();
                // 多单位
                Integer enableMultiUnit = getIntegerOrDefaultFromFormData(originData, ProductEnum.ENABLE_MULTI_UNIT.getAttr(), 0);
                Integer enableSerial = getIntegerOrDefaultFromFormData(originData, ProductEnum.ENABLE_SERIAL_NUMBER.getAttr(), 0);
                JSONObject unitObj = FastJsonHelper.getJsonObjectOrDefaultFromFormData(jsonObject, SelectProductEnum.UNIT.getAttr(), new JSONObject());
                if (Objects.equals(1, enableMultiUnit)) {
                    MultiUnitItemPoJo multiUnitItemPoJo = groupBaseUnitMap.getOrDefault(originData.getLong(ProductEnum.UNIT.getAttr()), new MultiUnitItemPoJo());
                    // 是多单位，但是是单单位的value，或没有值，补成基本单位
                    if (unitObj.isEmpty() || !StringUtil.isDigital(unitObj.getString(StringConstant.VALUE)) || unitObj.getLong(StringConstant.VALUE) < ProductConstant.MAX_SINGLE_UNIT_VALUE) {
                        unitObj.put(MultiUnitConstant.MULTI_UNIT_TEXT, multiUnitItemPoJo.getBaseName());
                        unitObj.put(MultiUnitConstant.VALUE, multiUnitItemPoJo.getBaseValue());
                        jsonObject.put(SelectProductEnum.UNIT.getAttr(), unitObj);
                    }
                    Long unitValue = unitObj.getLong(StringConstant.VALUE);
                    List<UnitItemPoJo> itemDataPoJoList = multiUnitItemPoJo.getItemDataPoJoList();
                    List<UnitItemPoJo> copyItemPojo = (List<UnitItemPoJo>)CloneUtil.deepClone(itemDataPoJoList);
                    originData.put(ProductConstant.TRANSFORM_UNIT_RATE, itemDataPoJoList);
                    jsonObject.put(ProductConstant.TRANSFORM_UNIT_RATE, itemDataPoJoList);
                    Map<Long, UnitItemPoJo> businessUnitMap = itemDataPoJoList.stream().collect(Collectors.toMap(UnitItemPoJo::getValue, data -> data));
                    if (!Objects.equals(businessType, XbbRefTypeEnum.PRODUCTION_ORDER.getCode())) {
                        copyItemPojo.removeIf(item -> !(Objects.equals(item.getValue(), unitValue) || Objects.equals(item.getIsBase(), 1)));
                    }
                    originData.put(ProductConstant.UNIT_RATE, copyItemPojo);
                    jsonObject.put(ProductConstant.UNIT_RATE, copyItemPojo);
                    boolean otherInOutStock = Objects.equals(businessType, XbbRefTypeEnum.INSTOCK.getCode()) || (Objects.equals(businessType, XbbRefTypeEnum.OUTSTOCK.getCode()) );
                    if (StockConstant.MULTI_UNIT_TYPE_LIST.contains(businessType) && !(StockConstant.SERIAL_TYPE_LIST.contains(businessType) && Objects.equals(enableSerial, 1)) && !otherInOutStock) {
                        // 是多单位业务类型而且不是（既开启序列号且是序列号业务类型）
                        originData.put(ProductEnum.ENABLE_MULTI_UNIT.getSaasAttr(), 1);
                        jsonObject.put(ProductEnum.ENABLE_MULTI_UNIT.getSaasAttr(), 1);
                    } else {
                        // 不是多单位业务类型，或者是（序列号产品且是序列号业务类型）,此时不能选单位，只能是基本单位
                        if (!otherInOutStock) {
                            originData.put(SelectProductEnum.NUM.getAttr(), Arith.mul(jsonObject.getDouble(SelectProductEnum.NUM.getAttr()), businessUnitMap.getOrDefault(unitValue, new UnitItemPoJo()).getRate()));
                            unitObj.put(MultiUnitConstant.MULTI_UNIT_TEXT, multiUnitItemPoJo.getBaseName());
                            unitObj.put(MultiUnitConstant.VALUE, multiUnitItemPoJo.getBaseValue());
                            originData.put(SelectProductEnum.UNIT.getAttr(), unitObj);
                        }
                        originData.put(ProductEnum.ENABLE_MULTI_UNIT.getSaasAttr(), 0);
                        jsonObject.put(ProductEnum.ENABLE_MULTI_UNIT.getSaasAttr(), 0);
                    }
                    originData.put(ProductEnum.UNIT.getAttr(), unitObj);
                } else {
                    originData.put(ProductEnum.ENABLE_MULTI_UNIT.getSaasAttr(), 0);
                    jsonObject.put(ProductEnum.ENABLE_MULTI_UNIT.getSaasAttr(), 0);
                }

                productService.setChildSpecification(Collections.singletonList(paasFormDataEntityExt),corpid);
                JSONObject data = paasFormDataEntityExt.getData();
                data.put(FieldTypeEnum.SERIALNO.getAlias(),paasFormDataEntityExt.getSerialNo());
                data.put("warehouse",productMaps.get(productId));
                JSONObject productData = new JSONObject();
                if (coverCostAndStock){
                    data.put(ProductEnum.COST.getAttr(),jsonObject.getDouble(SelectProductEnum.COST.getAttr()));
                }
                productData.put("data",data);
                productData.put("sourceData",data);
                productData.put("dataId",productId);
                jsonObject.put(SelectProductEnum.PRODUCT.getAttr(),productData);
                if (coverCostAndStock){
                    jsonObject.put(SelectProductEnum.STOCK.getAttr(),data.getDouble(ProductEnum.STOCK.getAttr()));
                }
                jsonObject.put(BusinessConstant.PRODUCT_SUB_ID,0);
                if (!thisToTarget.isEmpty()) {
                    Long businessProductId = jsonObject.getLong("businessProductId");
                    JSONObject productBusinessData = productBusinessDataMap.get(businessProductId);
                    ParseSingleRowDataDTO parseSingleRowDataDTO = new ParseSingleRowDataDTO();
                    BeanUtil.copyProperties(businessProductListRelyDTO, parseSingleRowDataDTO);
                    parseSingleRowDataDTO.setCreatorId(paasFormDataEntityExt.getCreatorId());
                    parseSingleRowDataDTO.setDataJsonObject(productBusinessData);
                    parseSingleRowDataDTO.setUserMap(userMap);
                    parseSingleRowDataDTO.setDepartmentMap(departmentMap);
                    parseSingleRowDataDTO.setExplainMap(subSourceExplainMap);
                    ParseSingleRowDataVO parseSingleRowDataVO = formDataUpdateGetAnalysisDataHelp.parseSingleRowData(parseSingleRowDataDTO);
                    if(Objects.isNull(parseSingleRowDataVO)){
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PARSE_SINGLE_ROW_DATA_FAILED);
                    }
                    JSONObject result = parseSingleRowDataVO.getResult();
                    JSONObject thisData = formatThisFormData(subThisExplainMap, thisToTarget, result);
                    jsonObject.putAll(thisData);
                }
            }
            formDataValidateProductHelp.loyalToProduct(productArray,corpid,businessProductListRelyDTO.getLoginUser());
        }
        productObj.put(attr,productArray);
        productObj.put(secondAttr,secondArray);
        productObj.put(thirdAttr, otherExpense);
        productObj.put(fourthAttr, discountAmount);
        productObj.put(fifthAttr, discount);
        productObj.put(refundAmountAttr, refundAmount);
        BusinessProductListRelyVO businessProductListRelyVO = new BusinessProductListRelyVO();
        businessProductListRelyVO.setProductArray(productObj);
        return businessProductListRelyVO;
    }

    @Override
    public Map<String, FieldAttrEntity> getProductRelyMap(String attr, LinkProductRelyEntity linkProductRelyEntity, Map<String, FieldAttrEntity> sourceExplainMap, Map<String, FieldAttrEntity> displayExplainListMap, Map<String, FieldAttrEntity> subLinkExplainMap, Map<String, String> thisToTarget) {
        Map<String, FieldAttrEntity> subDisplayExplainMap = null;
        if (Objects.nonNull(linkProductRelyEntity) && Objects.equals(displayExplainListMap.get(attr).getDefaultAttr().getDefaultType(), DefaultTypeEnum.PRODUCT_DATA_RELY.getAlias())) {
            List<SubRelyFieldPojo> subRelyFieldList = JSONArray.parseArray(JSON.toJSONString(linkProductRelyEntity.getSubRelyFieldList()), SubRelyFieldPojo.class);
            for (SubRelyFieldPojo subRelyFieldPojo : subRelyFieldList) {
                thisToTarget.put(subRelyFieldPojo.getThisField(), subRelyFieldPojo.getTargetField());
            }
            FieldAttrEntity linkFieldAttr = sourceExplainMap.get(linkProductRelyEntity.getLinkField());
            List<String> source = new ArrayList<>();
            subRelyFieldList.forEach(item->{
                source.add(linkProductRelyEntity.getLinkField() + StringConstant.POINT + item.getTargetField());
            });
            // 获取子表单字段
            List<? extends FieldAttrEntity> subLinkExplainList = linkFieldAttr.getSubForm().getItems();
            Iterator<? extends FieldAttrEntity> iterator = subLinkExplainList.iterator();
            while (iterator.hasNext()) {
                FieldAttrEntity fieldAttrEntity = iterator.next();
                String parent = fieldAttrEntity.getParentAttr();
                if (StringUtil.isNotEmpty(parent)) {
                    parent = parent + StringConstant.POINT;
                }
                if (!source.contains(parent + fieldAttrEntity.getAttr())) {
                    iterator.remove();
                    continue;
                }
                subLinkExplainMap.put(fieldAttrEntity.getAttr(), fieldAttrEntity);
            }
            List<? extends FieldAttrEntity> subDisplayExplainList = displayExplainListMap.get(attr).getSubForm().getItems();
            subDisplayExplainMap = ExplainUtil.getExplainMapByList(subDisplayExplainList);
        }
        return subDisplayExplainMap;
    }

    @Override
    public JSONObject formatThisFormData(Map<String, FieldAttrEntity> subDisplayExplainMap, Map<String, String> thisToTarget, JSONObject result) {
        JSONObject thisData = new JSONObject();
        // 遍历当前表单对应目标表单的字段，通过对应关系拿到数据
        Iterator<String> stringIterator = thisToTarget.keySet().iterator();
        while (stringIterator.hasNext()) {
            String thisKey = stringIterator.next();
            // 获取对应的字段
            String key = thisToTarget.get(thisKey);
            if (Objects.isNull(result.get(key))) {
                continue;
            }
            FieldAttrEntity displayField = subDisplayExplainMap.get(thisKey);
            if (Objects.isNull(displayField)) {
                continue;
            }
            HashMap<String, Object> itemMap = new HashMap<>();
            List<ItemPoJo> items = displayField.getItems();
            if (CollectionsUtil.isNotEmpty(items)) {
                items.forEach(itemPoJo -> {
                    itemMap.put(itemPoJo.getText(), itemPoJo.getValue());
                });
            }
            Integer thisKeyFieldType = displayField.getFieldType();
            FieldTypeEnum fieldTypeEnum = FieldTypeEnum.getFieldTypeEnum(thisKeyFieldType);
            assert fieldTypeEnum != null;
            switch (fieldTypeEnum) {
                case TEXT:
                case TEXTAREA:
                    if (result.get(key) instanceof Map || result.get(key) instanceof ItemPoJo) {
                        thisData.put(thisKey, result.getJSONObject(key).get("text"));
                    }else {
                        thisData.put(thisKey, result.get(key));
                    }
                    break;
                case COMBO:
                case RADIO_GROUP:
                    if (!(result.get(key) instanceof Map) &&  !(result.get(key) instanceof ItemPoJo)) {
                        // 单行文本一类的数据
                        JSONObject itemJSON = new JSONObject();
                        itemJSON.put("value", result.get(key));
                        itemJSON.put("text", result.get(key));
                        thisData.put(thisKey, itemJSON);
                    } else {
                        // 下拉框、单选按钮一类的数据
                        JSONObject itemJSON = new JSONObject();
                        Object value = result.getJSONObject(key).get("text");
                        itemJSON.put("value", itemMap.getOrDefault(String.valueOf(value), value));
                        itemJSON.put("text", value);
                        thisData.put(thisKey, itemJSON);
                    }
                    break;
                case COMBO_CHECK:
                case CHECKBOX_GROUP:
                    if (result.get(key) instanceof List) {
                        // 下拉多选和复选一类数据
                        JSONArray jsonArray = result.getJSONArray(key);
                        for (int j = 0; j < jsonArray.size(); j++) {
                            JSONObject obj = jsonArray.getJSONObject(j);
                            obj.put("value", itemMap.getOrDefault(obj.getString("text"), obj.getString("text")));
                            jsonArray.set(j, obj);
                        }
                        thisData.put(thisKey, jsonArray);
                    } else if (result.get(key) instanceof Map || result.get(key) instanceof ItemPoJo) {
                        // 下拉框、单选按钮一类的数据
                        JSONObject itemJSON = new JSONObject();
                        Object value = result.getJSONObject(key).get("text");
                        itemJSON.put("value", itemMap.getOrDefault(String.valueOf(value), value));
                        itemJSON.put("text", value);
                        JSONArray jsonArray = new JSONArray();
                        jsonArray.add(itemJSON);
                        thisData.put(thisKey, jsonArray);
                    } else {
                        // 单行文本一类的数据
                        JSONObject itemJSON = new JSONObject();
                        Object value = result.get(key);
                        itemJSON.put("value", value);
                        itemJSON.put("text", value);
                        JSONArray jsonArray = new JSONArray();
                        jsonArray.add(itemJSON);
                        thisData.put(thisKey, jsonArray);
                    }
                    break;
                default:
                    thisData.put(thisKey, result.get(key));
                    break;
            }
        }
        return thisData;
    }

    @Override
    public BusinessProductBatchListVO getProductAutoMatchBatch(BussinessProductBatchAutoMatchDTO bussinessProductBatchAutoMatchDTO) throws XbbException {
        return productStockInfoService.getProductAutoMatchBatch(bussinessProductBatchAutoMatchDTO);
    }

}
